12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406 |
- /* Everything about breakpoints, for GDB.
- Copyright (C) 1986-2022 Free Software Foundation, Inc.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "defs.h"
- #include "arch-utils.h"
- #include <ctype.h>
- #include "hashtab.h"
- #include "symtab.h"
- #include "frame.h"
- #include "breakpoint.h"
- #include "tracepoint.h"
- #include "gdbtypes.h"
- #include "expression.h"
- #include "gdbcore.h"
- #include "gdbcmd.h"
- #include "value.h"
- #include "command.h"
- #include "inferior.h"
- #include "infrun.h"
- #include "gdbthread.h"
- #include "target.h"
- #include "language.h"
- #include "gdb-demangle.h"
- #include "filenames.h"
- #include "annotate.h"
- #include "symfile.h"
- #include "objfiles.h"
- #include "source.h"
- #include "linespec.h"
- #include "completer.h"
- #include "ui-out.h"
- #include "cli/cli-script.h"
- #include "block.h"
- #include "solib.h"
- #include "solist.h"
- #include "observable.h"
- #include "memattr.h"
- #include "ada-lang.h"
- #include "top.h"
- #include "valprint.h"
- #include "jit.h"
- #include "parser-defs.h"
- #include "gdbsupport/gdb_regex.h"
- #include "probe.h"
- #include "cli/cli-utils.h"
- #include "stack.h"
- #include "ax-gdb.h"
- #include "dummy-frame.h"
- #include "interps.h"
- #include "gdbsupport/format.h"
- #include "thread-fsm.h"
- #include "tid-parse.h"
- #include "cli/cli-style.h"
- #include "cli/cli-decode.h"
- /* readline include files */
- #include "readline/tilde.h"
- /* readline defines this. */
- #undef savestring
- #include "mi/mi-common.h"
- #include "extension.h"
- #include <algorithm>
- #include "progspace-and-thread.h"
- #include "gdbsupport/array-view.h"
- #include "gdbsupport/gdb_optional.h"
- /* Prototypes for local functions. */
- static void map_breakpoint_numbers (const char *,
- gdb::function_view<void (breakpoint *)>);
- static void breakpoint_re_set_default (struct breakpoint *);
- static void
- create_sals_from_location_default (struct event_location *location,
- struct linespec_result *canonical,
- enum bptype type_wanted);
- static void create_breakpoints_sal_default (struct gdbarch *,
- struct linespec_result *,
- gdb::unique_xmalloc_ptr<char>,
- gdb::unique_xmalloc_ptr<char>,
- enum bptype,
- enum bpdisp, int, int,
- int,
- const struct breakpoint_ops *,
- int, int, int, unsigned);
- static std::vector<symtab_and_line> decode_location_default
- (struct breakpoint *b, struct event_location *location,
- struct program_space *search_pspace);
- static int can_use_hardware_watchpoint
- (const std::vector<value_ref_ptr> &vals);
- static void mention (struct breakpoint *);
- static struct breakpoint *set_raw_breakpoint_without_location (struct gdbarch *,
- enum bptype,
- const struct breakpoint_ops *);
- static struct bp_location *add_location_to_breakpoint (struct breakpoint *,
- const struct symtab_and_line *);
- /* This function is used in gdbtk sources and thus can not be made
- static. */
- static struct breakpoint *set_raw_breakpoint (struct gdbarch *gdbarch,
- struct symtab_and_line,
- enum bptype,
- const struct breakpoint_ops *);
- static struct breakpoint *
- momentary_breakpoint_from_master (struct breakpoint *orig,
- enum bptype type,
- const struct breakpoint_ops *ops,
- int loc_enabled);
- static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int);
- static CORE_ADDR adjust_breakpoint_address (struct gdbarch *gdbarch,
- CORE_ADDR bpaddr,
- enum bptype bptype);
- static void describe_other_breakpoints (struct gdbarch *,
- struct program_space *, CORE_ADDR,
- struct obj_section *, int);
- static int watchpoint_locations_match (struct bp_location *loc1,
- struct bp_location *loc2);
- static int breakpoint_locations_match (struct bp_location *loc1,
- struct bp_location *loc2,
- bool sw_hw_bps_match = false);
- static int breakpoint_location_address_match (struct bp_location *bl,
- const struct address_space *aspace,
- CORE_ADDR addr);
- static int breakpoint_location_address_range_overlap (struct bp_location *,
- const address_space *,
- CORE_ADDR, int);
- static int remove_breakpoint (struct bp_location *);
- static int remove_breakpoint_1 (struct bp_location *, enum remove_bp_reason);
- static enum print_stop_action print_bp_stop_message (bpstat *bs);
- static int hw_breakpoint_used_count (void);
- static int hw_watchpoint_use_count (struct breakpoint *);
- static int hw_watchpoint_used_count_others (struct breakpoint *except,
- enum bptype type,
- int *other_type_used);
- static void enable_breakpoint_disp (struct breakpoint *, enum bpdisp,
- int count);
- static void decref_bp_location (struct bp_location **loc);
- static struct bp_location *allocate_bp_location (struct breakpoint *bpt);
- /* update_global_location_list's modes of operation wrt to whether to
- insert locations now. */
- enum ugll_insert_mode
- {
- /* Don't insert any breakpoint locations into the inferior, only
- remove already-inserted locations that no longer should be
- inserted. Functions that delete a breakpoint or breakpoints
- should specify this mode, so that deleting a breakpoint doesn't
- have the side effect of inserting the locations of other
- breakpoints that are marked not-inserted, but should_be_inserted
- returns true on them.
- This behavior is useful is situations close to tear-down -- e.g.,
- after an exec, while the target still has execution, but
- breakpoint shadows of the previous executable image should *NOT*
- be restored to the new image; or before detaching, where the
- target still has execution and wants to delete breakpoints from
- GDB's lists, and all breakpoints had already been removed from
- the inferior. */
- UGLL_DONT_INSERT,
- /* May insert breakpoints iff breakpoints_should_be_inserted_now
- claims breakpoints should be inserted now. */
- UGLL_MAY_INSERT,
- /* Insert locations now, irrespective of
- breakpoints_should_be_inserted_now. E.g., say all threads are
- stopped right now, and the user did "continue". We need to
- insert breakpoints _before_ resuming the target, but
- UGLL_MAY_INSERT wouldn't insert them, because
- breakpoints_should_be_inserted_now returns false at that point,
- as no thread is running yet. */
- UGLL_INSERT
- };
- static void update_global_location_list (enum ugll_insert_mode);
- static void update_global_location_list_nothrow (enum ugll_insert_mode);
- static void insert_breakpoint_locations (void);
- static void trace_pass_command (const char *, int);
- static void set_tracepoint_count (int num);
- static bool is_masked_watchpoint (const struct breakpoint *b);
- /* Return 1 if B refers to a static tracepoint set by marker ("-m"), zero
- otherwise. */
- static int strace_marker_p (struct breakpoint *b);
- /* The breakpoint_ops structure to be inherited by all breakpoint_ops
- that are implemented on top of software or hardware breakpoints
- (user breakpoints, internal and momentary breakpoints, etc.). */
- static struct breakpoint_ops bkpt_base_breakpoint_ops;
- /* Internal breakpoints class type. */
- static struct breakpoint_ops internal_breakpoint_ops;
- /* Momentary breakpoints class type. */
- static struct breakpoint_ops momentary_breakpoint_ops;
- /* The breakpoint_ops structure to be used in regular user created
- breakpoints. */
- struct breakpoint_ops bkpt_breakpoint_ops;
- /* Breakpoints set on probes. */
- static struct breakpoint_ops bkpt_probe_breakpoint_ops;
- /* Tracepoints set on probes. */
- static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
- /* Dynamic printf class type. */
- struct breakpoint_ops dprintf_breakpoint_ops;
- /* The style in which to perform a dynamic printf. This is a user
- option because different output options have different tradeoffs;
- if GDB does the printing, there is better error handling if there
- is a problem with any of the arguments, but using an inferior
- function lets you have special-purpose printers and sending of
- output to the same place as compiled-in print functions. */
- static const char dprintf_style_gdb[] = "gdb";
- static const char dprintf_style_call[] = "call";
- static const char dprintf_style_agent[] = "agent";
- static const char *const dprintf_style_enums[] = {
- dprintf_style_gdb,
- dprintf_style_call,
- dprintf_style_agent,
- NULL
- };
- static const char *dprintf_style = dprintf_style_gdb;
- /* The function to use for dynamic printf if the preferred style is to
- call into the inferior. The value is simply a string that is
- copied into the command, so it can be anything that GDB can
- evaluate to a callable address, not necessarily a function name. */
- static std::string dprintf_function = "printf";
- /* The channel to use for dynamic printf if the preferred style is to
- call into the inferior; if a nonempty string, it will be passed to
- the call as the first argument, with the format string as the
- second. As with the dprintf function, this can be anything that
- GDB knows how to evaluate, so in addition to common choices like
- "stderr", this could be an app-specific expression like
- "mystreams[curlogger]". */
- static std::string dprintf_channel;
- /* True if dprintf commands should continue to operate even if GDB
- has disconnected. */
- static bool disconnected_dprintf = true;
- struct command_line *
- breakpoint_commands (struct breakpoint *b)
- {
- return b->commands ? b->commands.get () : NULL;
- }
- /* Flag indicating that a command has proceeded the inferior past the
- current breakpoint. */
- static bool breakpoint_proceeded;
- const char *
- bpdisp_text (enum bpdisp disp)
- {
- /* NOTE: the following values are a part of MI protocol and
- represent values of 'disp' field returned when inferior stops at
- a breakpoint. */
- static const char * const bpdisps[] = {"del", "dstp", "dis", "keep"};
- return bpdisps[(int) disp];
- }
- /* Prototypes for exported functions. */
- /* If FALSE, gdb will not use hardware support for watchpoints, even
- if such is available. */
- static int can_use_hw_watchpoints;
- static void
- show_can_use_hw_watchpoints (struct ui_file *file, int from_tty,
- struct cmd_list_element *c,
- const char *value)
- {
- gdb_printf (file,
- _("Debugger's willingness to use "
- "watchpoint hardware is %s.\n"),
- value);
- }
- /* If AUTO_BOOLEAN_FALSE, gdb will not attempt to create pending breakpoints.
- If AUTO_BOOLEAN_TRUE, gdb will automatically create pending breakpoints
- for unrecognized breakpoint locations.
- If AUTO_BOOLEAN_AUTO, gdb will query when breakpoints are unrecognized. */
- static enum auto_boolean pending_break_support;
- static void
- show_pending_break_support (struct ui_file *file, int from_tty,
- struct cmd_list_element *c,
- const char *value)
- {
- gdb_printf (file,
- _("Debugger's behavior regarding "
- "pending breakpoints is %s.\n"),
- value);
- }
- /* If true, gdb will automatically use hardware breakpoints for breakpoints
- set with "break" but falling in read-only memory.
- If false, gdb will warn about such breakpoints, but won't automatically
- use hardware breakpoints. */
- static bool automatic_hardware_breakpoints;
- static void
- show_automatic_hardware_breakpoints (struct ui_file *file, int from_tty,
- struct cmd_list_element *c,
- const char *value)
- {
- gdb_printf (file,
- _("Automatic usage of hardware breakpoints is %s.\n"),
- value);
- }
- /* If on, GDB keeps breakpoints inserted even if the inferior is
- stopped, and immediately inserts any new breakpoints as soon as
- they're created. If off (default), GDB keeps breakpoints off of
- the target as long as possible. That is, it delays inserting
- breakpoints until the next resume, and removes them again when the
- target fully stops. This is a bit safer in case GDB crashes while
- processing user input. */
- static bool always_inserted_mode = false;
- static void
- show_always_inserted_mode (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- gdb_printf (file, _("Always inserted breakpoint mode is %s.\n"),
- value);
- }
- /* See breakpoint.h. */
- int
- breakpoints_should_be_inserted_now (void)
- {
- if (gdbarch_has_global_breakpoints (target_gdbarch ()))
- {
- /* If breakpoints are global, they should be inserted even if no
- thread under gdb's control is running, or even if there are
- no threads under GDB's control yet. */
- return 1;
- }
- else
- {
- if (always_inserted_mode)
- {
- /* The user wants breakpoints inserted even if all threads
- are stopped. */
- return 1;
- }
- for (inferior *inf : all_inferiors ())
- if (inf->has_execution ()
- && threads_are_executing (inf->process_target ()))
- return 1;
- /* Don't remove breakpoints yet if, even though all threads are
- stopped, we still have events to process. */
- for (thread_info *tp : all_non_exited_threads ())
- if (tp->resumed () && tp->has_pending_waitstatus ())
- return 1;
- }
- return 0;
- }
- static const char condition_evaluation_both[] = "host or target";
- /* Modes for breakpoint condition evaluation. */
- static const char condition_evaluation_auto[] = "auto";
- static const char condition_evaluation_host[] = "host";
- static const char condition_evaluation_target[] = "target";
- static const char *const condition_evaluation_enums[] = {
- condition_evaluation_auto,
- condition_evaluation_host,
- condition_evaluation_target,
- NULL
- };
- /* Global that holds the current mode for breakpoint condition evaluation. */
- static const char *condition_evaluation_mode_1 = condition_evaluation_auto;
- /* Global that we use to display information to the user (gets its value from
- condition_evaluation_mode_1. */
- static const char *condition_evaluation_mode = condition_evaluation_auto;
- /* Translate a condition evaluation mode MODE into either "host"
- or "target". This is used mostly to translate from "auto" to the
- real setting that is being used. It returns the translated
- evaluation mode. */
- static const char *
- translate_condition_evaluation_mode (const char *mode)
- {
- if (mode == condition_evaluation_auto)
- {
- if (target_supports_evaluation_of_breakpoint_conditions ())
- return condition_evaluation_target;
- else
- return condition_evaluation_host;
- }
- else
- return mode;
- }
- /* Discovers what condition_evaluation_auto translates to. */
- static const char *
- breakpoint_condition_evaluation_mode (void)
- {
- return translate_condition_evaluation_mode (condition_evaluation_mode);
- }
- /* Return true if GDB should evaluate breakpoint conditions or false
- otherwise. */
- static int
- gdb_evaluates_breakpoint_condition_p (void)
- {
- const char *mode = breakpoint_condition_evaluation_mode ();
- return (mode == condition_evaluation_host);
- }
- /* Are we executing breakpoint commands? */
- static int executing_breakpoint_commands;
- /* Are overlay event breakpoints enabled? */
- static int overlay_events_enabled;
- /* See description in breakpoint.h. */
- bool target_exact_watchpoints = false;
- /* Walk the following statement or block through all breakpoints.
- ALL_BREAKPOINTS_SAFE does so even if the statement deletes the
- current breakpoint. */
- #define ALL_BREAKPOINTS_SAFE(B,TMP) \
- for (B = breakpoint_chain; \
- B ? (TMP=B->next, 1): 0; \
- B = TMP)
- /* Chains of all breakpoints defined. */
- static struct breakpoint *breakpoint_chain;
- /* See breakpoint.h. */
- breakpoint_range
- all_breakpoints ()
- {
- return breakpoint_range (breakpoint_chain);
- }
- /* See breakpoint.h. */
- breakpoint_safe_range
- all_breakpoints_safe ()
- {
- return breakpoint_safe_range (all_breakpoints ());
- }
- /* See breakpoint.h. */
- tracepoint_range
- all_tracepoints ()
- {
- return tracepoint_range (breakpoint_chain);
- }
- /* Array is sorted by bp_location_is_less_than - primarily by the ADDRESS. */
- static std::vector<bp_location *> bp_locations;
- /* See breakpoint.h. */
- const std::vector<bp_location *> &
- all_bp_locations ()
- {
- return bp_locations;
- }
- /* Range to iterate over breakpoint locations at a given address. */
- struct bp_locations_at_addr_range
- {
- using iterator = std::vector<bp_location *>::iterator;
- bp_locations_at_addr_range (CORE_ADDR addr)
- {
- struct compare
- {
- bool operator() (const bp_location *loc, CORE_ADDR addr_) const
- { return loc->address < addr_; }
- bool operator() (CORE_ADDR addr_, const bp_location *loc) const
- { return addr_ < loc->address; }
- };
- auto it_pair = std::equal_range (bp_locations.begin (), bp_locations.end (),
- addr, compare ());
- m_begin = it_pair.first;
- m_end = it_pair.second;
- }
- iterator begin () const
- { return m_begin; }
- iterator end () const
- { return m_end; }
- private:
- iterator m_begin;
- iterator m_end;
- };
- /* Return a range to iterate over all breakpoint locations exactly at address
- ADDR.
- If it's needed to iterate multiple times on the same range, it's possible
- to save the range in a local variable and use it multiple times:
- auto range = all_bp_locations_at_addr (addr);
- for (bp_location *loc : range)
- // use loc
- for (bp_location *loc : range)
- // use loc
- This saves a bit of time, as it avoids re-doing the binary searches to find
- the range's boundaries. Just remember not to change the bp_locations vector
- in the mean time, as it could make the range's iterators stale. */
- static bp_locations_at_addr_range
- all_bp_locations_at_addr (CORE_ADDR addr)
- {
- return bp_locations_at_addr_range (addr);
- }
- /* Maximum alignment offset between bp_target_info.PLACED_ADDRESS and
- ADDRESS for the current elements of BP_LOCATIONS which get a valid
- result from bp_location_has_shadow. You can use it for roughly
- limiting the subrange of BP_LOCATIONS to scan for shadow bytes for
- an address you need to read. */
- static CORE_ADDR bp_locations_placed_address_before_address_max;
- /* Maximum offset plus alignment between bp_target_info.PLACED_ADDRESS
- + bp_target_info.SHADOW_LEN and ADDRESS for the current elements of
- BP_LOCATIONS which get a valid result from bp_location_has_shadow.
- You can use it for roughly limiting the subrange of BP_LOCATIONS to
- scan for shadow bytes for an address you need to read. */
- static CORE_ADDR bp_locations_shadow_len_after_address_max;
- /* The locations that no longer correspond to any breakpoint, unlinked
- from the bp_locations array, but for which a hit may still be
- reported by a target. */
- static std::vector<bp_location *> moribund_locations;
- /* Number of last breakpoint made. */
- static int breakpoint_count;
- /* The value of `breakpoint_count' before the last command that
- created breakpoints. If the last (break-like) command created more
- than one breakpoint, then the difference between BREAKPOINT_COUNT
- and PREV_BREAKPOINT_COUNT is more than one. */
- static int prev_breakpoint_count;
- /* Number of last tracepoint made. */
- static int tracepoint_count;
- static struct cmd_list_element *breakpoint_set_cmdlist;
- static struct cmd_list_element *breakpoint_show_cmdlist;
- struct cmd_list_element *save_cmdlist;
- /* Return whether a breakpoint is an active enabled breakpoint. */
- static int
- breakpoint_enabled (struct breakpoint *b)
- {
- return (b->enable_state == bp_enabled);
- }
- /* Set breakpoint count to NUM. */
- static void
- set_breakpoint_count (int num)
- {
- prev_breakpoint_count = breakpoint_count;
- breakpoint_count = num;
- set_internalvar_integer (lookup_internalvar ("bpnum"), num);
- }
- /* Used by `start_rbreak_breakpoints' below, to record the current
- breakpoint count before "rbreak" creates any breakpoint. */
- static int rbreak_start_breakpoint_count;
- /* Called at the start an "rbreak" command to record the first
- breakpoint made. */
- scoped_rbreak_breakpoints::scoped_rbreak_breakpoints ()
- {
- rbreak_start_breakpoint_count = breakpoint_count;
- }
- /* Called at the end of an "rbreak" command to record the last
- breakpoint made. */
- scoped_rbreak_breakpoints::~scoped_rbreak_breakpoints ()
- {
- prev_breakpoint_count = rbreak_start_breakpoint_count;
- }
- /* Used in run_command to zero the hit count when a new run starts. */
- void
- clear_breakpoint_hit_counts (void)
- {
- for (breakpoint *b : all_breakpoints ())
- b->hit_count = 0;
- }
- /* Return the breakpoint with the specified number, or NULL
- if the number does not refer to an existing breakpoint. */
- struct breakpoint *
- get_breakpoint (int num)
- {
- for (breakpoint *b : all_breakpoints ())
- if (b->number == num)
- return b;
-
- return nullptr;
- }
- /* Mark locations as "conditions have changed" in case the target supports
- evaluating conditions on its side. */
- static void
- mark_breakpoint_modified (struct breakpoint *b)
- {
- /* This is only meaningful if the target is
- evaluating conditions and if the user has
- opted for condition evaluation on the target's
- side. */
- if (gdb_evaluates_breakpoint_condition_p ()
- || !target_supports_evaluation_of_breakpoint_conditions ())
- return;
- if (!is_breakpoint (b))
- return;
- for (bp_location *loc : b->locations ())
- loc->condition_changed = condition_modified;
- }
- /* Mark location as "conditions have changed" in case the target supports
- evaluating conditions on its side. */
- static void
- mark_breakpoint_location_modified (struct bp_location *loc)
- {
- /* This is only meaningful if the target is
- evaluating conditions and if the user has
- opted for condition evaluation on the target's
- side. */
- if (gdb_evaluates_breakpoint_condition_p ()
- || !target_supports_evaluation_of_breakpoint_conditions ())
- return;
- if (!is_breakpoint (loc->owner))
- return;
- loc->condition_changed = condition_modified;
- }
- /* Sets the condition-evaluation mode using the static global
- condition_evaluation_mode. */
- static void
- set_condition_evaluation_mode (const char *args, int from_tty,
- struct cmd_list_element *c)
- {
- const char *old_mode, *new_mode;
- if ((condition_evaluation_mode_1 == condition_evaluation_target)
- && !target_supports_evaluation_of_breakpoint_conditions ())
- {
- condition_evaluation_mode_1 = condition_evaluation_mode;
- warning (_("Target does not support breakpoint condition evaluation.\n"
- "Using host evaluation mode instead."));
- return;
- }
- new_mode = translate_condition_evaluation_mode (condition_evaluation_mode_1);
- old_mode = translate_condition_evaluation_mode (condition_evaluation_mode);
- /* Flip the switch. Flip it even if OLD_MODE == NEW_MODE as one of the
- settings was "auto". */
- condition_evaluation_mode = condition_evaluation_mode_1;
- /* Only update the mode if the user picked a different one. */
- if (new_mode != old_mode)
- {
- /* If the user switched to a different evaluation mode, we
- need to synch the changes with the target as follows:
- "host" -> "target": Send all (valid) conditions to the target.
- "target" -> "host": Remove all the conditions from the target.
- */
- if (new_mode == condition_evaluation_target)
- {
- /* Mark everything modified and synch conditions with the
- target. */
- for (bp_location *loc : all_bp_locations ())
- mark_breakpoint_location_modified (loc);
- }
- else
- {
- /* Manually mark non-duplicate locations to synch conditions
- with the target. We do this to remove all the conditions the
- target knows about. */
- for (bp_location *loc : all_bp_locations ())
- if (is_breakpoint (loc->owner) && loc->inserted)
- loc->needs_update = 1;
- }
- /* Do the update. */
- update_global_location_list (UGLL_MAY_INSERT);
- }
- return;
- }
- /* Shows the current mode of breakpoint condition evaluation. Explicitly shows
- what "auto" is translating to. */
- static void
- show_condition_evaluation_mode (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
- {
- if (condition_evaluation_mode == condition_evaluation_auto)
- gdb_printf (file,
- _("Breakpoint condition evaluation "
- "mode is %s (currently %s).\n"),
- value,
- breakpoint_condition_evaluation_mode ());
- else
- gdb_printf (file, _("Breakpoint condition evaluation mode is %s.\n"),
- value);
- }
- /* Parse COND_STRING in the context of LOC and set as the condition
- expression of LOC. BP_NUM is the number of LOC's owner, LOC_NUM is
- the number of LOC within its owner. In case of parsing error, mark
- LOC as DISABLED_BY_COND. In case of success, unset DISABLED_BY_COND. */
- static void
- set_breakpoint_location_condition (const char *cond_string, bp_location *loc,
- int bp_num, int loc_num)
- {
- bool has_junk = false;
- try
- {
- expression_up new_exp = parse_exp_1 (&cond_string, loc->address,
- block_for_pc (loc->address), 0);
- if (*cond_string != 0)
- has_junk = true;
- else
- {
- loc->cond = std::move (new_exp);
- if (loc->disabled_by_cond && loc->enabled)
- gdb_printf (_("Breakpoint %d's condition is now valid at "
- "location %d, enabling.\n"),
- bp_num, loc_num);
- loc->disabled_by_cond = false;
- }
- }
- catch (const gdb_exception_error &e)
- {
- if (loc->enabled)
- {
- /* Warn if a user-enabled location is now becoming disabled-by-cond.
- BP_NUM is 0 if the breakpoint is being defined for the first
- time using the "break ... if ..." command, and non-zero if
- already defined. */
- if (bp_num != 0)
- warning (_("failed to validate condition at location %d.%d, "
- "disabling:\n %s"), bp_num, loc_num, e.what ());
- else
- warning (_("failed to validate condition at location %d, "
- "disabling:\n %s"), loc_num, e.what ());
- }
- loc->disabled_by_cond = true;
- }
- if (has_junk)
- error (_("Garbage '%s' follows condition"), cond_string);
- }
- void
- set_breakpoint_condition (struct breakpoint *b, const char *exp,
- int from_tty, bool force)
- {
- if (*exp == 0)
- {
- b->cond_string.reset ();
- if (is_watchpoint (b))
- static_cast<watchpoint *> (b)->cond_exp.reset ();
- else
- {
- int loc_num = 1;
- for (bp_location *loc : b->locations ())
- {
- loc->cond.reset ();
- if (loc->disabled_by_cond && loc->enabled)
- gdb_printf (_("Breakpoint %d's condition is now valid at "
- "location %d, enabling.\n"),
- b->number, loc_num);
- loc->disabled_by_cond = false;
- loc_num++;
- /* No need to free the condition agent expression
- bytecode (if we have one). We will handle this
- when we go through update_global_location_list. */
- }
- }
- if (from_tty)
- gdb_printf (_("Breakpoint %d now unconditional.\n"), b->number);
- }
- else
- {
- if (is_watchpoint (b))
- {
- innermost_block_tracker tracker;
- const char *arg = exp;
- expression_up new_exp = parse_exp_1 (&arg, 0, 0, 0, &tracker);
- if (*arg != 0)
- error (_("Junk at end of expression"));
- watchpoint *w = static_cast<watchpoint *> (b);
- w->cond_exp = std::move (new_exp);
- w->cond_exp_valid_block = tracker.block ();
- }
- else
- {
- /* Parse and set condition expressions. We make two passes.
- In the first, we parse the condition string to see if it
- is valid in at least one location. If so, the condition
- would be accepted. So we go ahead and set the locations'
- conditions. In case no valid case is found, we throw
- the error and the condition string will be rejected.
- This two-pass approach is taken to avoid setting the
- state of locations in case of a reject. */
- for (bp_location *loc : b->locations ())
- {
- try
- {
- const char *arg = exp;
- parse_exp_1 (&arg, loc->address,
- block_for_pc (loc->address), 0);
- if (*arg != 0)
- error (_("Junk at end of expression"));
- break;
- }
- catch (const gdb_exception_error &e)
- {
- /* Condition string is invalid. If this happens to
- be the last loc, abandon (if not forced) or continue
- (if forced). */
- if (loc->next == nullptr && !force)
- throw;
- }
- }
- /* If we reach here, the condition is valid at some locations. */
- int loc_num = 1;
- for (bp_location *loc : b->locations ())
- {
- set_breakpoint_location_condition (exp, loc, b->number, loc_num);
- loc_num++;
- }
- }
- /* We know that the new condition parsed successfully. The
- condition string of the breakpoint can be safely updated. */
- b->cond_string = make_unique_xstrdup (exp);
- b->condition_not_parsed = 0;
- }
- mark_breakpoint_modified (b);
- gdb::observers::breakpoint_modified.notify (b);
- }
- /* See breakpoint.h. */
- void
- set_breakpoint_condition (int bpnum, const char *exp, int from_tty,
- bool force)
- {
- for (breakpoint *b : all_breakpoints ())
- if (b->number == bpnum)
- {
- /* Check if this breakpoint has a "stop" method implemented in an
- extension language. This method and conditions entered into GDB
- from the CLI are mutually exclusive. */
- const struct extension_language_defn *extlang
- = get_breakpoint_cond_ext_lang (b, EXT_LANG_NONE);
- if (extlang != NULL)
- {
- error (_("Only one stop condition allowed. There is currently"
- " a %s stop condition defined for this breakpoint."),
- ext_lang_capitalized_name (extlang));
- }
- set_breakpoint_condition (b, exp, from_tty, force);
- if (is_breakpoint (b))
- update_global_location_list (UGLL_MAY_INSERT);
- return;
- }
- error (_("No breakpoint number %d."), bpnum);
- }
- /* The options for the "condition" command. */
- struct condition_command_opts
- {
- /* For "-force". */
- bool force_condition = false;
- };
- static const gdb::option::option_def condition_command_option_defs[] = {
- gdb::option::flag_option_def<condition_command_opts> {
- "force",
- [] (condition_command_opts *opts) { return &opts->force_condition; },
- N_("Set the condition even if it is invalid for all current locations."),
- },
- };
- /* Create an option_def_group for the "condition" options, with
- CC_OPTS as context. */
- static inline gdb::option::option_def_group
- make_condition_command_options_def_group (condition_command_opts *cc_opts)
- {
- return {{condition_command_option_defs}, cc_opts};
- }
- /* Completion for the "condition" command. */
- static void
- condition_completer (struct cmd_list_element *cmd,
- completion_tracker &tracker,
- const char *text, const char * /*word*/)
- {
- bool has_no_arguments = (*text == '\0');
- condition_command_opts cc_opts;
- const auto group = make_condition_command_options_def_group (&cc_opts);
- if (gdb::option::complete_options
- (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group))
- return;
- text = skip_spaces (text);
- const char *space = skip_to_space (text);
- if (*space == '\0')
- {
- int len;
- if (text[0] == '$')
- {
- tracker.advance_custom_word_point_by (1);
- /* We don't support completion of history indices. */
- if (!isdigit (text[1]))
- complete_internalvar (tracker, &text[1]);
- return;
- }
- /* Suggest the "-force" flag if no arguments are given. If
- arguments were passed, they either already include the flag,
- or we are beyond the point of suggesting it because it's
- positionally the first argument. */
- if (has_no_arguments)
- gdb::option::complete_on_all_options (tracker, group);
- /* We're completing the breakpoint number. */
- len = strlen (text);
- for (breakpoint *b : all_breakpoints ())
- {
- char number[50];
- xsnprintf (number, sizeof (number), "%d", b->number);
- if (strncmp (number, text, len) == 0)
- tracker.add_completion (make_unique_xstrdup (number));
- }
- return;
- }
- /* We're completing the expression part. Skip the breakpoint num. */
- const char *exp_start = skip_spaces (space);
- tracker.advance_custom_word_point_by (exp_start - text);
- text = exp_start;
- const char *word = advance_to_expression_complete_word_point (tracker, text);
- expression_completer (cmd, tracker, text, word);
- }
- /* condition N EXP -- set break condition of breakpoint N to EXP. */
- static void
- condition_command (const char *arg, int from_tty)
- {
- const char *p;
- int bnum;
- if (arg == 0)
- error_no_arg (_("breakpoint number"));
- p = arg;
- /* Check if the "-force" flag was passed. */
- condition_command_opts cc_opts;
- const auto group = make_condition_command_options_def_group (&cc_opts);
- gdb::option::process_options
- (&p, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group);
- bnum = get_number (&p);
- if (bnum == 0)
- error (_("Bad breakpoint argument: '%s'"), arg);
- set_breakpoint_condition (bnum, p, from_tty, cc_opts.force_condition);
- }
- /* Check that COMMAND do not contain commands that are suitable
- only for tracepoints and not suitable for ordinary breakpoints.
- Throw if any such commands is found. */
- static void
- check_no_tracepoint_commands (struct command_line *commands)
- {
- struct command_line *c;
- for (c = commands; c; c = c->next)
- {
- if (c->control_type == while_stepping_control)
- error (_("The 'while-stepping' command can "
- "only be used for tracepoints"));
- check_no_tracepoint_commands (c->body_list_0.get ());
- check_no_tracepoint_commands (c->body_list_1.get ());
- /* Not that command parsing removes leading whitespace and comment
- lines and also empty lines. So, we only need to check for
- command directly. */
- if (strstr (c->line, "collect ") == c->line)
- error (_("The 'collect' command can only be used for tracepoints"));
- if (strstr (c->line, "teval ") == c->line)
- error (_("The 'teval' command can only be used for tracepoints"));
- }
- }
- struct longjmp_breakpoint : public breakpoint
- {
- ~longjmp_breakpoint () override;
- };
- /* Encapsulate tests for different types of tracepoints. */
- static bool
- is_tracepoint_type (bptype type)
- {
- return (type == bp_tracepoint
- || type == bp_fast_tracepoint
- || type == bp_static_tracepoint);
- }
- static bool
- is_longjmp_type (bptype type)
- {
- return type == bp_longjmp || type == bp_exception;
- }
- /* See breakpoint.h. */
- bool
- is_tracepoint (const struct breakpoint *b)
- {
- return is_tracepoint_type (b->type);
- }
- /* Factory function to create an appropriate instance of breakpoint given
- TYPE. */
- static std::unique_ptr<breakpoint>
- new_breakpoint_from_type (bptype type)
- {
- breakpoint *b;
- if (is_tracepoint_type (type))
- b = new tracepoint ();
- else if (is_longjmp_type (type))
- b = new longjmp_breakpoint ();
- else
- b = new breakpoint ();
- return std::unique_ptr<breakpoint> (b);
- }
- /* A helper function that validates that COMMANDS are valid for a
- breakpoint. This function will throw an exception if a problem is
- found. */
- static void
- validate_commands_for_breakpoint (struct breakpoint *b,
- struct command_line *commands)
- {
- if (is_tracepoint (b))
- {
- struct tracepoint *t = (struct tracepoint *) b;
- struct command_line *c;
- struct command_line *while_stepping = 0;
- /* Reset the while-stepping step count. The previous commands
- might have included a while-stepping action, while the new
- ones might not. */
- t->step_count = 0;
- /* We need to verify that each top-level element of commands is
- valid for tracepoints, that there's at most one
- while-stepping element, and that the while-stepping's body
- has valid tracing commands excluding nested while-stepping.
- We also need to validate the tracepoint action line in the
- context of the tracepoint --- validate_actionline actually
- has side effects, like setting the tracepoint's
- while-stepping STEP_COUNT, in addition to checking if the
- collect/teval actions parse and make sense in the
- tracepoint's context. */
- for (c = commands; c; c = c->next)
- {
- if (c->control_type == while_stepping_control)
- {
- if (b->type == bp_fast_tracepoint)
- error (_("The 'while-stepping' command "
- "cannot be used for fast tracepoint"));
- else if (b->type == bp_static_tracepoint)
- error (_("The 'while-stepping' command "
- "cannot be used for static tracepoint"));
- if (while_stepping)
- error (_("The 'while-stepping' command "
- "can be used only once"));
- else
- while_stepping = c;
- }
- validate_actionline (c->line, b);
- }
- if (while_stepping)
- {
- struct command_line *c2;
- gdb_assert (while_stepping->body_list_1 == nullptr);
- c2 = while_stepping->body_list_0.get ();
- for (; c2; c2 = c2->next)
- {
- if (c2->control_type == while_stepping_control)
- error (_("The 'while-stepping' command cannot be nested"));
- }
- }
- }
- else
- {
- check_no_tracepoint_commands (commands);
- }
- }
- /* Return a vector of all the static tracepoints set at ADDR. The
- caller is responsible for releasing the vector. */
- std::vector<breakpoint *>
- static_tracepoints_here (CORE_ADDR addr)
- {
- std::vector<breakpoint *> found;
- for (breakpoint *b : all_breakpoints ())
- if (b->type == bp_static_tracepoint)
- {
- for (bp_location *loc : b->locations ())
- if (loc->address == addr)
- found.push_back (b);
- }
- return found;
- }
- /* Set the command list of B to COMMANDS. If breakpoint is tracepoint,
- validate that only allowed commands are included. */
- void
- breakpoint_set_commands (struct breakpoint *b,
- counted_command_line &&commands)
- {
- validate_commands_for_breakpoint (b, commands.get ());
- b->commands = std::move (commands);
- gdb::observers::breakpoint_modified.notify (b);
- }
- /* Set the internal `silent' flag on the breakpoint. Note that this
- is not the same as the "silent" that may appear in the breakpoint's
- commands. */
- void
- breakpoint_set_silent (struct breakpoint *b, int silent)
- {
- int old_silent = b->silent;
- b->silent = silent;
- if (old_silent != silent)
- gdb::observers::breakpoint_modified.notify (b);
- }
- /* Set the thread for this breakpoint. If THREAD is -1, make the
- breakpoint work for any thread. */
- void
- breakpoint_set_thread (struct breakpoint *b, int thread)
- {
- int old_thread = b->thread;
- b->thread = thread;
- if (old_thread != thread)
- gdb::observers::breakpoint_modified.notify (b);
- }
- /* Set the task for this breakpoint. If TASK is 0, make the
- breakpoint work for any task. */
- void
- breakpoint_set_task (struct breakpoint *b, int task)
- {
- int old_task = b->task;
- b->task = task;
- if (old_task != task)
- gdb::observers::breakpoint_modified.notify (b);
- }
- static void
- commands_command_1 (const char *arg, int from_tty,
- struct command_line *control)
- {
- counted_command_line cmd;
- /* cmd_read will be true once we have read cmd. Note that cmd might still be
- NULL after the call to read_command_lines if the user provides an empty
- list of command by just typing "end". */
- bool cmd_read = false;
- std::string new_arg;
- if (arg == NULL || !*arg)
- {
- /* Argument not explicitly given. Synthesize it. */
- if (breakpoint_count - prev_breakpoint_count > 1)
- new_arg = string_printf ("%d-%d", prev_breakpoint_count + 1,
- breakpoint_count);
- else if (breakpoint_count > 0)
- new_arg = string_printf ("%d", breakpoint_count);
- }
- else
- {
- /* Create a copy of ARG. This is needed because the "commands"
- command may be coming from a script. In that case, the read
- line buffer is going to be overwritten in the lambda of
- 'map_breakpoint_numbers' below when reading the next line
- before we are are done parsing the breakpoint numbers. */
- new_arg = arg;
- }
- arg = new_arg.c_str ();
- map_breakpoint_numbers
- (arg, [&] (breakpoint *b)
- {
- if (!cmd_read)
- {
- gdb_assert (cmd == NULL);
- if (control != NULL)
- cmd = control->body_list_0;
- else
- {
- std::string str
- = string_printf (_("Type commands for breakpoint(s) "
- "%s, one per line."),
- arg);
- auto do_validate = [=] (const char *line)
- {
- validate_actionline (line, b);
- };
- gdb::function_view<void (const char *)> validator;
- if (is_tracepoint (b))
- validator = do_validate;
- cmd = read_command_lines (str.c_str (), from_tty, 1, validator);
- }
- cmd_read = true;
- }
- /* If a breakpoint was on the list more than once, we don't need to
- do anything. */
- if (b->commands != cmd)
- {
- validate_commands_for_breakpoint (b, cmd.get ());
- b->commands = cmd;
- gdb::observers::breakpoint_modified.notify (b);
- }
- });
- }
- static void
- commands_command (const char *arg, int from_tty)
- {
- commands_command_1 (arg, from_tty, NULL);
- }
- /* Like commands_command, but instead of reading the commands from
- input stream, takes them from an already parsed command structure.
- This is used by cli-script.c to DTRT with breakpoint commands
- that are part of if and while bodies. */
- enum command_control_type
- commands_from_control_command (const char *arg, struct command_line *cmd)
- {
- commands_command_1 (arg, 0, cmd);
- return simple_control;
- }
- /* Return non-zero if BL->TARGET_INFO contains valid information. */
- static int
- bp_location_has_shadow (struct bp_location *bl)
- {
- if (bl->loc_type != bp_loc_software_breakpoint)
- return 0;
- if (!bl->inserted)
- return 0;
- if (bl->target_info.shadow_len == 0)
- /* BL isn't valid, or doesn't shadow memory. */
- return 0;
- return 1;
- }
- /* Update BUF, which is LEN bytes read from the target address
- MEMADDR, by replacing a memory breakpoint with its shadowed
- contents.
- If READBUF is not NULL, this buffer must not overlap with the of
- the breakpoint location's shadow_contents buffer. Otherwise, a
- failed assertion internal error will be raised. */
- static void
- one_breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
- const gdb_byte *writebuf_org,
- ULONGEST memaddr, LONGEST len,
- struct bp_target_info *target_info,
- struct gdbarch *gdbarch)
- {
- /* Now do full processing of the found relevant range of elements. */
- CORE_ADDR bp_addr = 0;
- int bp_size = 0;
- int bptoffset = 0;
- if (!breakpoint_address_match (target_info->placed_address_space, 0,
- current_program_space->aspace, 0))
- {
- /* The breakpoint is inserted in a different address space. */
- return;
- }
- /* Addresses and length of the part of the breakpoint that
- we need to copy. */
- bp_addr = target_info->placed_address;
- bp_size = target_info->shadow_len;
- if (bp_addr + bp_size <= memaddr)
- {
- /* The breakpoint is entirely before the chunk of memory we are
- reading. */
- return;
- }
- if (bp_addr >= memaddr + len)
- {
- /* The breakpoint is entirely after the chunk of memory we are
- reading. */
- return;
- }
- /* Offset within shadow_contents. */
- if (bp_addr < memaddr)
- {
- /* Only copy the second part of the breakpoint. */
- bp_size -= memaddr - bp_addr;
- bptoffset = memaddr - bp_addr;
- bp_addr = memaddr;
- }
- if (bp_addr + bp_size > memaddr + len)
- {
- /* Only copy the first part of the breakpoint. */
- bp_size -= (bp_addr + bp_size) - (memaddr + len);
- }
- if (readbuf != NULL)
- {
- /* Verify that the readbuf buffer does not overlap with the
- shadow_contents buffer. */
- gdb_assert (target_info->shadow_contents >= readbuf + len
- || readbuf >= (target_info->shadow_contents
- + target_info->shadow_len));
- /* Update the read buffer with this inserted breakpoint's
- shadow. */
- memcpy (readbuf + bp_addr - memaddr,
- target_info->shadow_contents + bptoffset, bp_size);
- }
- else
- {
- const unsigned char *bp;
- CORE_ADDR addr = target_info->reqstd_address;
- int placed_size;
- /* Update the shadow with what we want to write to memory. */
- memcpy (target_info->shadow_contents + bptoffset,
- writebuf_org + bp_addr - memaddr, bp_size);
- /* Determine appropriate breakpoint contents and size for this
- address. */
- bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &placed_size);
- /* Update the final write buffer with this inserted
- breakpoint's INSN. */
- memcpy (writebuf + bp_addr - memaddr, bp + bptoffset, bp_size);
- }
- }
- /* Update BUF, which is LEN bytes read from the target address MEMADDR,
- by replacing any memory breakpoints with their shadowed contents.
- If READBUF is not NULL, this buffer must not overlap with any of
- the breakpoint location's shadow_contents buffers. Otherwise,
- a failed assertion internal error will be raised.
- The range of shadowed area by each bp_location is:
- bl->address - bp_locations_placed_address_before_address_max
- up to bl->address + bp_locations_shadow_len_after_address_max
- The range we were requested to resolve shadows for is:
- memaddr ... memaddr + len
- Thus the safe cutoff boundaries for performance optimization are
- memaddr + len <= (bl->address
- - bp_locations_placed_address_before_address_max)
- and:
- bl->address + bp_locations_shadow_len_after_address_max <= memaddr */
- void
- breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf,
- const gdb_byte *writebuf_org,
- ULONGEST memaddr, LONGEST len)
- {
- /* Left boundary, right boundary and median element of our binary
- search. */
- unsigned bc_l, bc_r, bc;
- /* Find BC_L which is a leftmost element which may affect BUF
- content. It is safe to report lower value but a failure to
- report higher one. */
- bc_l = 0;
- bc_r = bp_locations.size ();
- while (bc_l + 1 < bc_r)
- {
- struct bp_location *bl;
- bc = (bc_l + bc_r) / 2;
- bl = bp_locations[bc];
- /* Check first BL->ADDRESS will not overflow due to the added
- constant. Then advance the left boundary only if we are sure
- the BC element can in no way affect the BUF content (MEMADDR
- to MEMADDR + LEN range).
- Use the BP_LOCATIONS_SHADOW_LEN_AFTER_ADDRESS_MAX safety
- offset so that we cannot miss a breakpoint with its shadow
- range tail still reaching MEMADDR. */
- if ((bl->address + bp_locations_shadow_len_after_address_max
- >= bl->address)
- && (bl->address + bp_locations_shadow_len_after_address_max
- <= memaddr))
- bc_l = bc;
- else
- bc_r = bc;
- }
- /* Due to the binary search above, we need to make sure we pick the
- first location that's at BC_L's address. E.g., if there are
- multiple locations at the same address, BC_L may end up pointing
- at a duplicate location, and miss the "master"/"inserted"
- location. Say, given locations L1, L2 and L3 at addresses A and
- B:
- L1@A, L2@A, L3@B, ...
- BC_L could end up pointing at location L2, while the "master"
- location could be L1. Since the `loc->inserted' flag is only set
- on "master" locations, we'd forget to restore the shadow of L1
- and L2. */
- while (bc_l > 0
- && bp_locations[bc_l]->address == bp_locations[bc_l - 1]->address)
- bc_l--;
- /* Now do full processing of the found relevant range of elements. */
- for (bc = bc_l; bc < bp_locations.size (); bc++)
- {
- struct bp_location *bl = bp_locations[bc];
- /* bp_location array has BL->OWNER always non-NULL. */
- if (bl->owner->type == bp_none)
- warning (_("reading through apparently deleted breakpoint #%d?"),
- bl->owner->number);
- /* Performance optimization: any further element can no longer affect BUF
- content. */
- if (bl->address >= bp_locations_placed_address_before_address_max
- && (memaddr + len
- <= (bl->address
- - bp_locations_placed_address_before_address_max)))
- break;
- if (!bp_location_has_shadow (bl))
- continue;
- one_breakpoint_xfer_memory (readbuf, writebuf, writebuf_org,
- memaddr, len, &bl->target_info, bl->gdbarch);
- }
- }
- /* See breakpoint.h. */
- bool
- is_breakpoint (const struct breakpoint *bpt)
- {
- return (bpt->type == bp_breakpoint
- || bpt->type == bp_hardware_breakpoint
- || bpt->type == bp_dprintf);
- }
- /* Return true if BPT is of any hardware watchpoint kind. */
- static bool
- is_hardware_watchpoint (const struct breakpoint *bpt)
- {
- return (bpt->type == bp_hardware_watchpoint
- || bpt->type == bp_read_watchpoint
- || bpt->type == bp_access_watchpoint);
- }
- /* See breakpoint.h. */
- bool
- is_watchpoint (const struct breakpoint *bpt)
- {
- return (is_hardware_watchpoint (bpt)
- || bpt->type == bp_watchpoint);
- }
- /* Returns true if the current thread and its running state are safe
- to evaluate or update watchpoint B. Watchpoints on local
- expressions need to be evaluated in the context of the thread that
- was current when the watchpoint was created, and, that thread needs
- to be stopped to be able to select the correct frame context.
- Watchpoints on global expressions can be evaluated on any thread,
- and in any state. It is presently left to the target allowing
- memory accesses when threads are running. */
- static int
- watchpoint_in_thread_scope (struct watchpoint *b)
- {
- return (b->pspace == current_program_space
- && (b->watchpoint_thread == null_ptid
- || (inferior_ptid == b->watchpoint_thread
- && !inferior_thread ()->executing ())));
- }
- /* Set watchpoint B to disp_del_at_next_stop, even including its possible
- associated bp_watchpoint_scope breakpoint. */
- static void
- watchpoint_del_at_next_stop (struct watchpoint *w)
- {
- if (w->related_breakpoint != w)
- {
- gdb_assert (w->related_breakpoint->type == bp_watchpoint_scope);
- gdb_assert (w->related_breakpoint->related_breakpoint == w);
- w->related_breakpoint->disposition = disp_del_at_next_stop;
- w->related_breakpoint->related_breakpoint = w->related_breakpoint;
- w->related_breakpoint = w;
- }
- w->disposition = disp_del_at_next_stop;
- }
- /* Extract a bitfield value from value VAL using the bit parameters contained in
- watchpoint W. */
- static struct value *
- extract_bitfield_from_watchpoint_value (struct watchpoint *w, struct value *val)
- {
- struct value *bit_val;
- if (val == NULL)
- return NULL;
- bit_val = allocate_value (value_type (val));
- unpack_value_bitfield (bit_val,
- w->val_bitpos,
- w->val_bitsize,
- value_contents_for_printing (val).data (),
- value_offset (val),
- val);
- return bit_val;
- }
- /* Allocate a dummy location and add it to B, which must be a software
- watchpoint. This is required because even if a software watchpoint
- is not watching any memory, bpstat_stop_status requires a location
- to be able to report stops. */
- static void
- software_watchpoint_add_no_memory_location (struct breakpoint *b,
- struct program_space *pspace)
- {
- gdb_assert (b->type == bp_watchpoint && b->loc == NULL);
- b->loc = allocate_bp_location (b);
- b->loc->pspace = pspace;
- b->loc->address = -1;
- b->loc->length = -1;
- }
- /* Returns true if B is a software watchpoint that is not watching any
- memory (e.g., "watch $pc"). */
- static bool
- is_no_memory_software_watchpoint (struct breakpoint *b)
- {
- return (b->type == bp_watchpoint
- && b->loc != NULL
- && b->loc->next == NULL
- && b->loc->address == -1
- && b->loc->length == -1);
- }
- /* Assuming that B is a watchpoint:
- - Reparse watchpoint expression, if REPARSE is non-zero
- - Evaluate expression and store the result in B->val
- - Evaluate the condition if there is one, and store the result
- in b->loc->cond.
- - Update the list of values that must be watched in B->loc.
- If the watchpoint disposition is disp_del_at_next_stop, then do
- nothing. If this is local watchpoint that is out of scope, delete
- it.
- Even with `set breakpoint always-inserted on' the watchpoints are
- removed + inserted on each stop here. Normal breakpoints must
- never be removed because they might be missed by a running thread
- when debugging in non-stop mode. On the other hand, hardware
- watchpoints (is_hardware_watchpoint; processed here) are specific
- to each LWP since they are stored in each LWP's hardware debug
- registers. Therefore, such LWP must be stopped first in order to
- be able to modify its hardware watchpoints.
- Hardware watchpoints must be reset exactly once after being
- presented to the user. It cannot be done sooner, because it would
- reset the data used to present the watchpoint hit to the user. And
- it must not be done later because it could display the same single
- watchpoint hit during multiple GDB stops. Note that the latter is
- relevant only to the hardware watchpoint types bp_read_watchpoint
- and bp_access_watchpoint. False hit by bp_hardware_watchpoint is
- not user-visible - its hit is suppressed if the memory content has
- not changed.
- The following constraints influence the location where we can reset
- hardware watchpoints:
- * target_stopped_by_watchpoint and target_stopped_data_address are
- called several times when GDB stops.
- [linux]
- * Multiple hardware watchpoints can be hit at the same time,
- causing GDB to stop. GDB only presents one hardware watchpoint
- hit at a time as the reason for stopping, and all the other hits
- are presented later, one after the other, each time the user
- requests the execution to be resumed. Execution is not resumed
- for the threads still having pending hit event stored in
- LWP_INFO->STATUS. While the watchpoint is already removed from
- the inferior on the first stop the thread hit event is kept being
- reported from its cached value by linux_nat_stopped_data_address
- until the real thread resume happens after the watchpoint gets
- presented and thus its LWP_INFO->STATUS gets reset.
- Therefore the hardware watchpoint hit can get safely reset on the
- watchpoint removal from inferior. */
- static void
- update_watchpoint (struct watchpoint *b, int reparse)
- {
- int within_current_scope;
- struct frame_id saved_frame_id;
- int frame_saved;
- /* If this is a local watchpoint, we only want to check if the
- watchpoint frame is in scope if the current thread is the thread
- that was used to create the watchpoint. */
- if (!watchpoint_in_thread_scope (b))
- return;
- if (b->disposition == disp_del_at_next_stop)
- return;
-
- frame_saved = 0;
- /* Determine if the watchpoint is within scope. */
- if (b->exp_valid_block == NULL)
- within_current_scope = 1;
- else
- {
- struct frame_info *fi = get_current_frame ();
- struct gdbarch *frame_arch = get_frame_arch (fi);
- CORE_ADDR frame_pc = get_frame_pc (fi);
- /* If we're at a point where the stack has been destroyed
- (e.g. in a function epilogue), unwinding may not work
- properly. Do not attempt to recreate locations at this
- point. See similar comments in watchpoint_check. */
- if (gdbarch_stack_frame_destroyed_p (frame_arch, frame_pc))
- return;
- /* Save the current frame's ID so we can restore it after
- evaluating the watchpoint expression on its own frame. */
- /* FIXME drow/2003-09-09: It would be nice if evaluate_expression
- took a frame parameter, so that we didn't have to change the
- selected frame. */
- frame_saved = 1;
- saved_frame_id = get_frame_id (get_selected_frame (NULL));
- fi = frame_find_by_id (b->watchpoint_frame);
- within_current_scope = (fi != NULL);
- if (within_current_scope)
- select_frame (fi);
- }
- /* We don't free locations. They are stored in the bp_location array
- and update_global_location_list will eventually delete them and
- remove breakpoints if needed. */
- b->loc = NULL;
- if (within_current_scope && reparse)
- {
- const char *s;
- b->exp.reset ();
- s = (b->exp_string_reparse
- ? b->exp_string_reparse.get ()
- : b->exp_string.get ());
- b->exp = parse_exp_1 (&s, 0, b->exp_valid_block, 0);
- /* If the meaning of expression itself changed, the old value is
- no longer relevant. We don't want to report a watchpoint hit
- to the user when the old value and the new value may actually
- be completely different objects. */
- b->val = NULL;
- b->val_valid = false;
- /* Note that unlike with breakpoints, the watchpoint's condition
- expression is stored in the breakpoint object, not in the
- locations (re)created below. */
- if (b->cond_string != NULL)
- {
- b->cond_exp.reset ();
- s = b->cond_string.get ();
- b->cond_exp = parse_exp_1 (&s, 0, b->cond_exp_valid_block, 0);
- }
- }
- /* If we failed to parse the expression, for example because
- it refers to a global variable in a not-yet-loaded shared library,
- don't try to insert watchpoint. We don't automatically delete
- such watchpoint, though, since failure to parse expression
- is different from out-of-scope watchpoint. */
- if (!target_has_execution ())
- {
- /* Without execution, memory can't change. No use to try and
- set watchpoint locations. The watchpoint will be reset when
- the target gains execution, through breakpoint_re_set. */
- if (!can_use_hw_watchpoints)
- {
- if (b->ops->works_in_software_mode (b))
- b->type = bp_watchpoint;
- else
- error (_("Can't set read/access watchpoint when "
- "hardware watchpoints are disabled."));
- }
- }
- else if (within_current_scope && b->exp)
- {
- std::vector<value_ref_ptr> val_chain;
- struct value *v, *result;
- struct program_space *frame_pspace;
- fetch_subexp_value (b->exp.get (), b->exp->op.get (), &v, &result,
- &val_chain, false);
- /* Avoid setting b->val if it's already set. The meaning of
- b->val is 'the last value' user saw, and we should update
- it only if we reported that last value to user. As it
- happens, the code that reports it updates b->val directly.
- We don't keep track of the memory value for masked
- watchpoints. */
- if (!b->val_valid && !is_masked_watchpoint (b))
- {
- if (b->val_bitsize != 0)
- v = extract_bitfield_from_watchpoint_value (b, v);
- b->val = release_value (v);
- b->val_valid = true;
- }
- frame_pspace = get_frame_program_space (get_selected_frame (NULL));
- /* Look at each value on the value chain. */
- gdb_assert (!val_chain.empty ());
- for (const value_ref_ptr &iter : val_chain)
- {
- v = iter.get ();
- /* If it's a memory location, and GDB actually needed
- its contents to evaluate the expression, then we
- must watch it. If the first value returned is
- still lazy, that means an error occurred reading it;
- watch it anyway in case it becomes readable. */
- if (VALUE_LVAL (v) == lval_memory
- && (v == val_chain[0] || ! value_lazy (v)))
- {
- struct type *vtype = check_typedef (value_type (v));
- /* We only watch structs and arrays if user asked
- for it explicitly, never if they just happen to
- appear in the middle of some value chain. */
- if (v == result
- || (vtype->code () != TYPE_CODE_STRUCT
- && vtype->code () != TYPE_CODE_ARRAY))
- {
- CORE_ADDR addr;
- enum target_hw_bp_type type;
- struct bp_location *loc, **tmp;
- int bitpos = 0, bitsize = 0;
- if (value_bitsize (v) != 0)
- {
- /* Extract the bit parameters out from the bitfield
- sub-expression. */
- bitpos = value_bitpos (v);
- bitsize = value_bitsize (v);
- }
- else if (v == result && b->val_bitsize != 0)
- {
- /* If VAL_BITSIZE != 0 then RESULT is actually a bitfield
- lvalue whose bit parameters are saved in the fields
- VAL_BITPOS and VAL_BITSIZE. */
- bitpos = b->val_bitpos;
- bitsize = b->val_bitsize;
- }
- addr = value_address (v);
- if (bitsize != 0)
- {
- /* Skip the bytes that don't contain the bitfield. */
- addr += bitpos / 8;
- }
- type = hw_write;
- if (b->type == bp_read_watchpoint)
- type = hw_read;
- else if (b->type == bp_access_watchpoint)
- type = hw_access;
- loc = allocate_bp_location (b);
- for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
- ;
- *tmp = loc;
- loc->gdbarch = value_type (v)->arch ();
- loc->pspace = frame_pspace;
- loc->address = address_significant (loc->gdbarch, addr);
- if (bitsize != 0)
- {
- /* Just cover the bytes that make up the bitfield. */
- loc->length = ((bitpos % 8) + bitsize + 7) / 8;
- }
- else
- loc->length = TYPE_LENGTH (value_type (v));
- loc->watchpoint_type = type;
- }
- }
- }
- /* Change the type of breakpoint between hardware assisted or
- an ordinary watchpoint depending on the hardware support
- and free hardware slots. REPARSE is set when the inferior
- is started. */
- if (reparse)
- {
- int reg_cnt;
- enum bp_loc_type loc_type;
- reg_cnt = can_use_hardware_watchpoint (val_chain);
- if (reg_cnt)
- {
- int i, target_resources_ok, other_type_used;
- enum bptype type;
- /* Use an exact watchpoint when there's only one memory region to be
- watched, and only one debug register is needed to watch it. */
- b->exact = target_exact_watchpoints && reg_cnt == 1;
- /* We need to determine how many resources are already
- used for all other hardware watchpoints plus this one
- to see if we still have enough resources to also fit
- this watchpoint in as well. */
- /* If this is a software watchpoint, we try to turn it
- to a hardware one -- count resources as if B was of
- hardware watchpoint type. */
- type = b->type;
- if (type == bp_watchpoint)
- type = bp_hardware_watchpoint;
- /* This watchpoint may or may not have been placed on
- the list yet at this point (it won't be in the list
- if we're trying to create it for the first time,
- through watch_command), so always account for it
- manually. */
- /* Count resources used by all watchpoints except B. */
- i = hw_watchpoint_used_count_others (b, type, &other_type_used);
- /* Add in the resources needed for B. */
- i += hw_watchpoint_use_count (b);
- target_resources_ok
- = target_can_use_hardware_watchpoint (type, i, other_type_used);
- if (target_resources_ok <= 0)
- {
- int sw_mode = b->ops->works_in_software_mode (b);
- if (target_resources_ok == 0 && !sw_mode)
- error (_("Target does not support this type of "
- "hardware watchpoint."));
- else if (target_resources_ok < 0 && !sw_mode)
- error (_("There are not enough available hardware "
- "resources for this watchpoint."));
- /* Downgrade to software watchpoint. */
- b->type = bp_watchpoint;
- }
- else
- {
- /* If this was a software watchpoint, we've just
- found we have enough resources to turn it to a
- hardware watchpoint. Otherwise, this is a
- nop. */
- b->type = type;
- }
- }
- else if (!b->ops->works_in_software_mode (b))
- {
- if (!can_use_hw_watchpoints)
- error (_("Can't set read/access watchpoint when "
- "hardware watchpoints are disabled."));
- else
- error (_("Expression cannot be implemented with "
- "read/access watchpoint."));
- }
- else
- b->type = bp_watchpoint;
- loc_type = (b->type == bp_watchpoint? bp_loc_other
- : bp_loc_hardware_watchpoint);
- for (bp_location *bl : b->locations ())
- bl->loc_type = loc_type;
- }
- /* If a software watchpoint is not watching any memory, then the
- above left it without any location set up. But,
- bpstat_stop_status requires a location to be able to report
- stops, so make sure there's at least a dummy one. */
- if (b->type == bp_watchpoint && b->loc == NULL)
- software_watchpoint_add_no_memory_location (b, frame_pspace);
- }
- else if (!within_current_scope)
- {
- gdb_printf (_("\
- Watchpoint %d deleted because the program has left the block\n\
- in which its expression is valid.\n"),
- b->number);
- watchpoint_del_at_next_stop (b);
- }
- /* Restore the selected frame. */
- if (frame_saved)
- select_frame (frame_find_by_id (saved_frame_id));
- }
- /* Returns 1 iff breakpoint location should be
- inserted in the inferior. We don't differentiate the type of BL's owner
- (breakpoint vs. tracepoint), although insert_location in tracepoint's
- breakpoint_ops is not defined, because in insert_bp_location,
- tracepoint's insert_location will not be called. */
- static int
- should_be_inserted (struct bp_location *bl)
- {
- if (bl->owner == NULL || !breakpoint_enabled (bl->owner))
- return 0;
- if (bl->owner->disposition == disp_del_at_next_stop)
- return 0;
- if (!bl->enabled || bl->disabled_by_cond
- || bl->shlib_disabled || bl->duplicate)
- return 0;
- if (user_breakpoint_p (bl->owner) && bl->pspace->executing_startup)
- return 0;
- /* This is set for example, when we're attached to the parent of a
- vfork, and have detached from the child. The child is running
- free, and we expect it to do an exec or exit, at which point the
- OS makes the parent schedulable again (and the target reports
- that the vfork is done). Until the child is done with the shared
- memory region, do not insert breakpoints in the parent, otherwise
- the child could still trip on the parent's breakpoints. Since
- the parent is blocked anyway, it won't miss any breakpoint. */
- if (bl->pspace->breakpoints_not_allowed)
- return 0;
- /* Don't insert a breakpoint if we're trying to step past its
- location, except if the breakpoint is a single-step breakpoint,
- and the breakpoint's thread is the thread which is stepping past
- a breakpoint. */
- if ((bl->loc_type == bp_loc_software_breakpoint
- || bl->loc_type == bp_loc_hardware_breakpoint)
- && stepping_past_instruction_at (bl->pspace->aspace,
- bl->address)
- /* The single-step breakpoint may be inserted at the location
- we're trying to step if the instruction branches to itself.
- However, the instruction won't be executed at all and it may
- break the semantics of the instruction, for example, the
- instruction is a conditional branch or updates some flags.
- We can't fix it unless GDB is able to emulate the instruction
- or switch to displaced stepping. */
- && !(bl->owner->type == bp_single_step
- && thread_is_stepping_over_breakpoint (bl->owner->thread)))
- {
- infrun_debug_printf ("skipping breakpoint: stepping past insn at: %s",
- paddress (bl->gdbarch, bl->address));
- return 0;
- }
- /* Don't insert watchpoints if we're trying to step past the
- instruction that triggered one. */
- if ((bl->loc_type == bp_loc_hardware_watchpoint)
- && stepping_past_nonsteppable_watchpoint ())
- {
- infrun_debug_printf ("stepping past non-steppable watchpoint. "
- "skipping watchpoint at %s:%d",
- paddress (bl->gdbarch, bl->address), bl->length);
- return 0;
- }
- return 1;
- }
- /* Same as should_be_inserted but does the check assuming
- that the location is not duplicated. */
- static int
- unduplicated_should_be_inserted (struct bp_location *bl)
- {
- int result;
- const int save_duplicate = bl->duplicate;
- bl->duplicate = 0;
- result = should_be_inserted (bl);
- bl->duplicate = save_duplicate;
- return result;
- }
- /* Parses a conditional described by an expression COND into an
- agent expression bytecode suitable for evaluation
- by the bytecode interpreter. Return NULL if there was
- any error during parsing. */
- static agent_expr_up
- parse_cond_to_aexpr (CORE_ADDR scope, struct expression *cond)
- {
- if (cond == NULL)
- return NULL;
- agent_expr_up aexpr;
- /* We don't want to stop processing, so catch any errors
- that may show up. */
- try
- {
- aexpr = gen_eval_for_expr (scope, cond);
- }
- catch (const gdb_exception_error &ex)
- {
- /* If we got here, it means the condition could not be parsed to a valid
- bytecode expression and thus can't be evaluated on the target's side.
- It's no use iterating through the conditions. */
- }
- /* We have a valid agent expression. */
- return aexpr;
- }
- /* Based on location BL, create a list of breakpoint conditions to be
- passed on to the target. If we have duplicated locations with different
- conditions, we will add such conditions to the list. The idea is that the
- target will evaluate the list of conditions and will only notify GDB when
- one of them is true. */
- static void
- build_target_condition_list (struct bp_location *bl)
- {
- int null_condition_or_parse_error = 0;
- int modified = bl->needs_update;
- /* Release conditions left over from a previous insert. */
- bl->target_info.conditions.clear ();
- /* This is only meaningful if the target is
- evaluating conditions and if the user has
- opted for condition evaluation on the target's
- side. */
- if (gdb_evaluates_breakpoint_condition_p ()
- || !target_supports_evaluation_of_breakpoint_conditions ())
- return;
- auto loc_range = all_bp_locations_at_addr (bl->address);
- /* Do a first pass to check for locations with no assigned
- conditions or conditions that fail to parse to a valid agent
- expression bytecode. If any of these happen, then it's no use to
- send conditions to the target since this location will always
- trigger and generate a response back to GDB. Note we consider
- all locations at the same address irrespective of type, i.e.,
- even if the locations aren't considered duplicates (e.g.,
- software breakpoint and hardware breakpoint at the same
- address). */
- for (bp_location *loc : loc_range)
- {
- if (is_breakpoint (loc->owner) && loc->pspace->num == bl->pspace->num)
- {
- if (modified)
- {
- /* Re-parse the conditions since something changed. In that
- case we already freed the condition bytecodes (see
- force_breakpoint_reinsertion). We just
- need to parse the condition to bytecodes again. */
- loc->cond_bytecode = parse_cond_to_aexpr (bl->address,
- loc->cond.get ());
- }
- /* If we have a NULL bytecode expression, it means something
- went wrong or we have a null condition expression. */
- if (!loc->cond_bytecode)
- {
- null_condition_or_parse_error = 1;
- break;
- }
- }
- }
- /* If any of these happened, it means we will have to evaluate the conditions
- for the location's address on gdb's side. It is no use keeping bytecodes
- for all the other duplicate locations, thus we free all of them here.
- This is so we have a finer control over which locations' conditions are
- being evaluated by GDB or the remote stub. */
- if (null_condition_or_parse_error)
- {
- for (bp_location *loc : loc_range)
- {
- if (is_breakpoint (loc->owner) && loc->pspace->num == bl->pspace->num)
- {
- /* Only go as far as the first NULL bytecode is
- located. */
- if (!loc->cond_bytecode)
- return;
- loc->cond_bytecode.reset ();
- }
- }
- }
- /* No NULL conditions or failed bytecode generation. Build a
- condition list for this location's address. If we have software
- and hardware locations at the same address, they aren't
- considered duplicates, but we still marge all the conditions
- anyway, as it's simpler, and doesn't really make a practical
- difference. */
- for (bp_location *loc : loc_range)
- if (loc->cond
- && is_breakpoint (loc->owner)
- && loc->pspace->num == bl->pspace->num
- && loc->owner->enable_state == bp_enabled
- && loc->enabled
- && !loc->disabled_by_cond)
- {
- /* Add the condition to the vector. This will be used later
- to send the conditions to the target. */
- bl->target_info.conditions.push_back (loc->cond_bytecode.get ());
- }
- return;
- }
- /* Parses a command described by string CMD into an agent expression
- bytecode suitable for evaluation by the bytecode interpreter.
- Return NULL if there was any error during parsing. */
- static agent_expr_up
- parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
- {
- const char *cmdrest;
- const char *format_start, *format_end;
- struct gdbarch *gdbarch = get_current_arch ();
- if (cmd == NULL)
- return NULL;
- cmdrest = cmd;
- if (*cmdrest == ',')
- ++cmdrest;
- cmdrest = skip_spaces (cmdrest);
- if (*cmdrest++ != '"')
- error (_("No format string following the location"));
- format_start = cmdrest;
- format_pieces fpieces (&cmdrest);
- format_end = cmdrest;
- if (*cmdrest++ != '"')
- error (_("Bad format string, non-terminated '\"'."));
-
- cmdrest = skip_spaces (cmdrest);
- if (!(*cmdrest == ',' || *cmdrest == '\0'))
- error (_("Invalid argument syntax"));
- if (*cmdrest == ',')
- cmdrest++;
- cmdrest = skip_spaces (cmdrest);
- /* For each argument, make an expression. */
- std::vector<struct expression *> argvec;
- while (*cmdrest != '\0')
- {
- const char *cmd1;
- cmd1 = cmdrest;
- expression_up expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1);
- argvec.push_back (expr.release ());
- cmdrest = cmd1;
- if (*cmdrest == ',')
- ++cmdrest;
- }
- agent_expr_up aexpr;
- /* We don't want to stop processing, so catch any errors
- that may show up. */
- try
- {
- aexpr = gen_printf (scope, gdbarch, 0, 0,
- format_start, format_end - format_start,
- argvec.size (), argvec.data ());
- }
- catch (const gdb_exception_error &ex)
- {
- /* If we got here, it means the command could not be parsed to a valid
- bytecode expression and thus can't be evaluated on the target's side.
- It's no use iterating through the other commands. */
- }
- /* We have a valid agent expression, return it. */
- return aexpr;
- }
- /* Based on location BL, create a list of breakpoint commands to be
- passed on to the target. If we have duplicated locations with
- different commands, we will add any such to the list. */
- static void
- build_target_command_list (struct bp_location *bl)
- {
- int null_command_or_parse_error = 0;
- int modified = bl->needs_update;
- /* Clear commands left over from a previous insert. */
- bl->target_info.tcommands.clear ();
- if (!target_can_run_breakpoint_commands ())
- return;
- /* For now, limit to agent-style dprintf breakpoints. */
- if (dprintf_style != dprintf_style_agent)
- return;
- auto loc_range = all_bp_locations_at_addr (bl->address);
- /* For now, if we have any location at the same address that isn't a
- dprintf, don't install the target-side commands, as that would
- make the breakpoint not be reported to the core, and we'd lose
- control. */
- for (bp_location *loc : loc_range)
- if (is_breakpoint (loc->owner)
- && loc->pspace->num == bl->pspace->num
- && loc->owner->type != bp_dprintf)
- return;
- /* Do a first pass to check for locations with no assigned
- conditions or conditions that fail to parse to a valid agent expression
- bytecode. If any of these happen, then it's no use to send conditions
- to the target since this location will always trigger and generate a
- response back to GDB. */
- for (bp_location *loc : loc_range)
- {
- if (is_breakpoint (loc->owner) && loc->pspace->num == bl->pspace->num)
- {
- if (modified)
- {
- /* Re-parse the commands since something changed. In that
- case we already freed the command bytecodes (see
- force_breakpoint_reinsertion). We just
- need to parse the command to bytecodes again. */
- loc->cmd_bytecode
- = parse_cmd_to_aexpr (bl->address,
- loc->owner->extra_string.get ());
- }
- /* If we have a NULL bytecode expression, it means something
- went wrong or we have a null command expression. */
- if (!loc->cmd_bytecode)
- {
- null_command_or_parse_error = 1;
- break;
- }
- }
- }
- /* If anything failed, then we're not doing target-side commands,
- and so clean up. */
- if (null_command_or_parse_error)
- {
- for (bp_location *loc : loc_range)
- if (is_breakpoint (loc->owner)
- && loc->pspace->num == bl->pspace->num)
- {
- /* Only go as far as the first NULL bytecode is
- located. */
- if (loc->cmd_bytecode == NULL)
- return;
- loc->cmd_bytecode.reset ();
- }
- }
- /* No NULL commands or failed bytecode generation. Build a command
- list for all duplicate locations at this location's address.
- Note that here we must care for whether the breakpoint location
- types are considered duplicates, otherwise, say, if we have a
- software and hardware location at the same address, the target
- could end up running the commands twice. For the moment, we only
- support targets-side commands with dprintf, but it doesn't hurt
- to be pedantically correct in case that changes. */
- for (bp_location *loc : loc_range)
- if (breakpoint_locations_match (bl, loc)
- && loc->owner->extra_string
- && is_breakpoint (loc->owner)
- && loc->pspace->num == bl->pspace->num
- && loc->owner->enable_state == bp_enabled
- && loc->enabled
- && !loc->disabled_by_cond)
- {
- /* Add the command to the vector. This will be used later
- to send the commands to the target. */
- bl->target_info.tcommands.push_back (loc->cmd_bytecode.get ());
- }
- bl->target_info.persist = 0;
- /* Maybe flag this location as persistent. */
- if (bl->owner->type == bp_dprintf && disconnected_dprintf)
- bl->target_info.persist = 1;
- }
- /* Return the kind of breakpoint on address *ADDR. Get the kind
- of breakpoint according to ADDR except single-step breakpoint.
- Get the kind of single-step breakpoint according to the current
- registers state. */
- static int
- breakpoint_kind (struct bp_location *bl, CORE_ADDR *addr)
- {
- if (bl->owner->type == bp_single_step)
- {
- struct thread_info *thr = find_thread_global_id (bl->owner->thread);
- struct regcache *regcache;
- regcache = get_thread_regcache (thr);
- return gdbarch_breakpoint_kind_from_current_state (bl->gdbarch,
- regcache, addr);
- }
- else
- return gdbarch_breakpoint_kind_from_pc (bl->gdbarch, addr);
- }
- /* Insert a low-level "breakpoint" of some type. BL is the breakpoint
- location. Any error messages are printed to TMP_ERROR_STREAM; and
- DISABLED_BREAKS, and HW_BREAKPOINT_ERROR are used to report problems.
- Returns 0 for success, 1 if the bp_location type is not supported or
- -1 for failure.
- NOTE drow/2003-09-09: This routine could be broken down to an
- object-style method for each breakpoint or catchpoint type. */
- static int
- insert_bp_location (struct bp_location *bl,
- struct ui_file *tmp_error_stream,
- int *disabled_breaks,
- int *hw_breakpoint_error,
- int *hw_bp_error_explained_already)
- {
- gdb_exception bp_excpt;
- if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update))
- return 0;
- /* Note we don't initialize bl->target_info, as that wipes out
- the breakpoint location's shadow_contents if the breakpoint
- is still inserted at that location. This in turn breaks
- target_read_memory which depends on these buffers when
- a memory read is requested at the breakpoint location:
- Once the target_info has been wiped, we fail to see that
- we have a breakpoint inserted at that address and thus
- read the breakpoint instead of returning the data saved in
- the breakpoint location's shadow contents. */
- bl->target_info.reqstd_address = bl->address;
- bl->target_info.placed_address_space = bl->pspace->aspace;
- bl->target_info.length = bl->length;
- /* When working with target-side conditions, we must pass all the conditions
- for the same breakpoint address down to the target since GDB will not
- insert those locations. With a list of breakpoint conditions, the target
- can decide when to stop and notify GDB. */
- if (is_breakpoint (bl->owner))
- {
- build_target_condition_list (bl);
- build_target_command_list (bl);
- /* Reset the modification marker. */
- bl->needs_update = 0;
- }
- /* If "set breakpoint auto-hw" is "on" and a software breakpoint was
- set at a read-only address, then a breakpoint location will have
- been changed to hardware breakpoint before we get here. If it is
- "off" however, error out before actually trying to insert the
- breakpoint, with a nicer error message. */
- if (bl->loc_type == bp_loc_software_breakpoint
- && !automatic_hardware_breakpoints)
- {
- mem_region *mr = lookup_mem_region (bl->address);
- if (mr != nullptr && mr->attrib.mode != MEM_RW)
- {
- gdb_printf (tmp_error_stream,
- _("Cannot insert breakpoint %d.\n"
- "Cannot set software breakpoint "
- "at read-only address %s\n"),
- bl->owner->number,
- paddress (bl->gdbarch, bl->address));
- return 1;
- }
- }
- if (bl->loc_type == bp_loc_software_breakpoint
- || bl->loc_type == bp_loc_hardware_breakpoint)
- {
- /* First check to see if we have to handle an overlay. */
- if (overlay_debugging == ovly_off
- || bl->section == NULL
- || !(section_is_overlay (bl->section)))
- {
- /* No overlay handling: just set the breakpoint. */
- try
- {
- int val;
- val = bl->owner->ops->insert_location (bl);
- if (val)
- bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR};
- }
- catch (gdb_exception &e)
- {
- bp_excpt = std::move (e);
- }
- }
- else
- {
- /* This breakpoint is in an overlay section.
- Shall we set a breakpoint at the LMA? */
- if (!overlay_events_enabled)
- {
- /* Yes -- overlay event support is not active,
- so we must try to set a breakpoint at the LMA.
- This will not work for a hardware breakpoint. */
- if (bl->loc_type == bp_loc_hardware_breakpoint)
- warning (_("hardware breakpoint %d not supported in overlay!"),
- bl->owner->number);
- else
- {
- CORE_ADDR addr = overlay_unmapped_address (bl->address,
- bl->section);
- /* Set a software (trap) breakpoint at the LMA. */
- bl->overlay_target_info = bl->target_info;
- bl->overlay_target_info.reqstd_address = addr;
- /* No overlay handling: just set the breakpoint. */
- try
- {
- int val;
- bl->overlay_target_info.kind
- = breakpoint_kind (bl, &addr);
- bl->overlay_target_info.placed_address = addr;
- val = target_insert_breakpoint (bl->gdbarch,
- &bl->overlay_target_info);
- if (val)
- bp_excpt
- = gdb_exception {RETURN_ERROR, GENERIC_ERROR};
- }
- catch (gdb_exception &e)
- {
- bp_excpt = std::move (e);
- }
- if (bp_excpt.reason != 0)
- gdb_printf (tmp_error_stream,
- "Overlay breakpoint %d "
- "failed: in ROM?\n",
- bl->owner->number);
- }
- }
- /* Shall we set a breakpoint at the VMA? */
- if (section_is_mapped (bl->section))
- {
- /* Yes. This overlay section is mapped into memory. */
- try
- {
- int val;
- val = bl->owner->ops->insert_location (bl);
- if (val)
- bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR};
- }
- catch (gdb_exception &e)
- {
- bp_excpt = std::move (e);
- }
- }
- else
- {
- /* No. This breakpoint will not be inserted.
- No error, but do not mark the bp as 'inserted'. */
- return 0;
- }
- }
- if (bp_excpt.reason != 0)
- {
- /* Can't set the breakpoint. */
- /* If the target has closed then it will have deleted any
- breakpoints inserted within the target inferior, as a result
- any further attempts to interact with the breakpoint objects
- is not possible. Just rethrow the error. */
- if (bp_excpt.error == TARGET_CLOSE_ERROR)
- throw bp_excpt;
- gdb_assert (bl->owner != nullptr);
- /* In some cases, we might not be able to insert a
- breakpoint in a shared library that has already been
- removed, but we have not yet processed the shlib unload
- event. Unfortunately, some targets that implement
- breakpoint insertion themselves can't tell why the
- breakpoint insertion failed (e.g., the remote target
- doesn't define error codes), so we must treat generic
- errors as memory errors. */
- if (bp_excpt.reason == RETURN_ERROR
- && (bp_excpt.error == GENERIC_ERROR
- || bp_excpt.error == MEMORY_ERROR)
- && bl->loc_type == bp_loc_software_breakpoint
- && (solib_name_from_address (bl->pspace, bl->address)
- || shared_objfile_contains_address_p (bl->pspace,
- bl->address)))
- {
- /* See also: disable_breakpoints_in_shlibs. */
- bl->shlib_disabled = 1;
- gdb::observers::breakpoint_modified.notify (bl->owner);
- if (!*disabled_breaks)
- {
- gdb_printf (tmp_error_stream,
- "Cannot insert breakpoint %d.\n",
- bl->owner->number);
- gdb_printf (tmp_error_stream,
- "Temporarily disabling shared "
- "library breakpoints:\n");
- }
- *disabled_breaks = 1;
- gdb_printf (tmp_error_stream,
- "breakpoint #%d\n", bl->owner->number);
- return 0;
- }
- else
- {
- if (bl->loc_type == bp_loc_hardware_breakpoint)
- {
- *hw_breakpoint_error = 1;
- *hw_bp_error_explained_already = bp_excpt.message != NULL;
- gdb_printf (tmp_error_stream,
- "Cannot insert hardware breakpoint %d%s",
- bl->owner->number,
- bp_excpt.message ? ":" : ".\n");
- if (bp_excpt.message != NULL)
- gdb_printf (tmp_error_stream, "%s.\n",
- bp_excpt.what ());
- }
- else
- {
- if (bp_excpt.message == NULL)
- {
- std::string message
- = memory_error_message (TARGET_XFER_E_IO,
- bl->gdbarch, bl->address);
- gdb_printf (tmp_error_stream,
- "Cannot insert breakpoint %d.\n"
- "%s\n",
- bl->owner->number, message.c_str ());
- }
- else
- {
- gdb_printf (tmp_error_stream,
- "Cannot insert breakpoint %d: %s\n",
- bl->owner->number,
- bp_excpt.what ());
- }
- }
- return 1;
- }
- }
- else
- bl->inserted = 1;
- return 0;
- }
- else if (bl->loc_type == bp_loc_hardware_watchpoint
- /* NOTE drow/2003-09-08: This state only exists for removing
- watchpoints. It's not clear that it's necessary... */
- && bl->owner->disposition != disp_del_at_next_stop)
- {
- int val;
- gdb_assert (bl->owner->ops != NULL
- && bl->owner->ops->insert_location != NULL);
- val = bl->owner->ops->insert_location (bl);
- /* If trying to set a read-watchpoint, and it turns out it's not
- supported, try emulating one with an access watchpoint. */
- if (val == 1 && bl->watchpoint_type == hw_read)
- {
- /* But don't try to insert it, if there's already another
- hw_access location that would be considered a duplicate
- of this one. */
- for (bp_location *loc : all_bp_locations ())
- if (loc != bl
- && loc->watchpoint_type == hw_access
- && watchpoint_locations_match (bl, loc))
- {
- bl->duplicate = 1;
- bl->inserted = 1;
- bl->target_info = loc->target_info;
- bl->watchpoint_type = hw_access;
- val = 0;
- break;
- }
- if (val == 1)
- {
- bl->watchpoint_type = hw_access;
- val = bl->owner->ops->insert_location (bl);
- if (val)
- /* Back to the original value. */
- bl->watchpoint_type = hw_read;
- }
- }
- bl->inserted = (val == 0);
- }
- else if (bl->owner->type == bp_catchpoint)
- {
- int val;
- gdb_assert (bl->owner->ops != NULL
- && bl->owner->ops->insert_location != NULL);
- val = bl->owner->ops->insert_location (bl);
- if (val)
- {
- bl->owner->enable_state = bp_disabled;
- if (val == 1)
- warning (_("\
- Error inserting catchpoint %d: Your system does not support this type\n\
- of catchpoint."), bl->owner->number);
- else
- warning (_("Error inserting catchpoint %d."), bl->owner->number);
- }
- bl->inserted = (val == 0);
- /* We've already printed an error message if there was a problem
- inserting this catchpoint, and we've disabled the catchpoint,
- so just return success. */
- return 0;
- }
- return 0;
- }
- /* This function is called when program space PSPACE is about to be
- deleted. It takes care of updating breakpoints to not reference
- PSPACE anymore. */
- void
- breakpoint_program_space_exit (struct program_space *pspace)
- {
- /* Remove any breakpoint that was set through this program space. */
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->pspace == pspace)
- delete_breakpoint (b);
- /* Breakpoints set through other program spaces could have locations
- bound to PSPACE as well. Remove those. */
- for (bp_location *loc : all_bp_locations ())
- {
- struct bp_location *tmp;
- if (loc->pspace == pspace)
- {
- /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL. */
- if (loc->owner->loc == loc)
- loc->owner->loc = loc->next;
- else
- for (tmp = loc->owner->loc; tmp->next != NULL; tmp = tmp->next)
- if (tmp->next == loc)
- {
- tmp->next = loc->next;
- break;
- }
- }
- }
- /* Now update the global location list to permanently delete the
- removed locations above. */
- update_global_location_list (UGLL_DONT_INSERT);
- }
- /* Make sure all breakpoints are inserted in inferior.
- Throws exception on any error.
- A breakpoint that is already inserted won't be inserted
- again, so calling this function twice is safe. */
- void
- insert_breakpoints (void)
- {
- for (breakpoint *bpt : all_breakpoints ())
- if (is_hardware_watchpoint (bpt))
- {
- struct watchpoint *w = (struct watchpoint *) bpt;
- update_watchpoint (w, 0 /* don't reparse. */);
- }
- /* Updating watchpoints creates new locations, so update the global
- location list. Explicitly tell ugll to insert locations and
- ignore breakpoints_always_inserted_mode. Also,
- update_global_location_list tries to "upgrade" software
- breakpoints to hardware breakpoints to handle "set breakpoint
- auto-hw", so we need to call it even if we don't have new
- locations. */
- update_global_location_list (UGLL_INSERT);
- }
- /* This is used when we need to synch breakpoint conditions between GDB and the
- target. It is the case with deleting and disabling of breakpoints when using
- always-inserted mode. */
- static void
- update_inserted_breakpoint_locations (void)
- {
- int error_flag = 0;
- int val = 0;
- int disabled_breaks = 0;
- int hw_breakpoint_error = 0;
- int hw_bp_details_reported = 0;
- string_file tmp_error_stream;
- /* Explicitly mark the warning -- this will only be printed if
- there was an error. */
- tmp_error_stream.puts ("Warning:\n");
- scoped_restore_current_pspace_and_thread restore_pspace_thread;
- for (bp_location *bl : all_bp_locations ())
- {
- /* We only want to update software breakpoints and hardware
- breakpoints. */
- if (!is_breakpoint (bl->owner))
- continue;
- /* We only want to update locations that are already inserted
- and need updating. This is to avoid unwanted insertion during
- deletion of breakpoints. */
- if (!bl->inserted || !bl->needs_update)
- continue;
- switch_to_program_space_and_thread (bl->pspace);
- /* For targets that support global breakpoints, there's no need
- to select an inferior to insert breakpoint to. In fact, even
- if we aren't attached to any process yet, we should still
- insert breakpoints. */
- if (!gdbarch_has_global_breakpoints (target_gdbarch ())
- && (inferior_ptid == null_ptid || !target_has_execution ()))
- continue;
- val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
- &hw_breakpoint_error, &hw_bp_details_reported);
- if (val)
- error_flag = val;
- }
- if (error_flag)
- {
- target_terminal::ours_for_output ();
- error_stream (tmp_error_stream);
- }
- }
- /* Used when starting or continuing the program. */
- static void
- insert_breakpoint_locations (void)
- {
- int error_flag = 0;
- int val = 0;
- int disabled_breaks = 0;
- int hw_breakpoint_error = 0;
- int hw_bp_error_explained_already = 0;
- string_file tmp_error_stream;
- /* Explicitly mark the warning -- this will only be printed if
- there was an error. */
- tmp_error_stream.puts ("Warning:\n");
- scoped_restore_current_pspace_and_thread restore_pspace_thread;
- for (bp_location *bl : all_bp_locations ())
- {
- if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update))
- continue;
- /* There is no point inserting thread-specific breakpoints if
- the thread no longer exists. ALL_BP_LOCATIONS bp_location
- has BL->OWNER always non-NULL. */
- if (bl->owner->thread != -1
- && !valid_global_thread_id (bl->owner->thread))
- continue;
- switch_to_program_space_and_thread (bl->pspace);
- /* For targets that support global breakpoints, there's no need
- to select an inferior to insert breakpoint to. In fact, even
- if we aren't attached to any process yet, we should still
- insert breakpoints. */
- if (!gdbarch_has_global_breakpoints (target_gdbarch ())
- && (inferior_ptid == null_ptid || !target_has_execution ()))
- continue;
- val = insert_bp_location (bl, &tmp_error_stream, &disabled_breaks,
- &hw_breakpoint_error, &hw_bp_error_explained_already);
- if (val)
- error_flag = val;
- }
- /* If we failed to insert all locations of a watchpoint, remove
- them, as half-inserted watchpoint is of limited use. */
- for (breakpoint *bpt : all_breakpoints ())
- {
- int some_failed = 0;
- if (!is_hardware_watchpoint (bpt))
- continue;
- if (!breakpoint_enabled (bpt))
- continue;
- if (bpt->disposition == disp_del_at_next_stop)
- continue;
-
- for (bp_location *loc : bpt->locations ())
- if (!loc->inserted && should_be_inserted (loc))
- {
- some_failed = 1;
- break;
- }
- if (some_failed)
- {
- for (bp_location *loc : bpt->locations ())
- if (loc->inserted)
- remove_breakpoint (loc);
- hw_breakpoint_error = 1;
- tmp_error_stream.printf ("Could not insert "
- "hardware watchpoint %d.\n",
- bpt->number);
- error_flag = -1;
- }
- }
- if (error_flag)
- {
- /* If a hardware breakpoint or watchpoint was inserted, add a
- message about possibly exhausted resources. */
- if (hw_breakpoint_error && !hw_bp_error_explained_already)
- {
- tmp_error_stream.printf ("Could not insert hardware breakpoints:\n\
- You may have requested too many hardware breakpoints/watchpoints.\n");
- }
- target_terminal::ours_for_output ();
- error_stream (tmp_error_stream);
- }
- }
- /* Used when the program stops.
- Returns zero if successful, or non-zero if there was a problem
- removing a breakpoint location. */
- int
- remove_breakpoints (void)
- {
- int val = 0;
- for (bp_location *bl : all_bp_locations ())
- if (bl->inserted && !is_tracepoint (bl->owner))
- val |= remove_breakpoint (bl);
- return val;
- }
- /* When a thread exits, remove breakpoints that are related to
- that thread. */
- static void
- remove_threaded_breakpoints (struct thread_info *tp, int silent)
- {
- for (breakpoint *b : all_breakpoints_safe ())
- {
- if (b->thread == tp->global_num && user_breakpoint_p (b))
- {
- b->disposition = disp_del_at_next_stop;
- gdb_printf (_("\
- Thread-specific breakpoint %d deleted - thread %s no longer in the thread list.\n"),
- b->number, print_thread_id (tp));
- /* Hide it from the user. */
- b->number = 0;
- }
- }
- }
- /* See breakpoint.h. */
- void
- remove_breakpoints_inf (inferior *inf)
- {
- int val;
- for (bp_location *bl : all_bp_locations ())
- {
- if (bl->pspace != inf->pspace)
- continue;
- if (bl->inserted && !bl->target_info.persist)
- {
- val = remove_breakpoint (bl);
- if (val != 0)
- return;
- }
- }
- }
- static int internal_breakpoint_number = -1;
- /* Set the breakpoint number of B, depending on the value of INTERNAL.
- If INTERNAL is non-zero, the breakpoint number will be populated
- from internal_breakpoint_number and that variable decremented.
- Otherwise the breakpoint number will be populated from
- breakpoint_count and that value incremented. Internal breakpoints
- do not set the internal var bpnum. */
- static void
- set_breakpoint_number (int internal, struct breakpoint *b)
- {
- if (internal)
- b->number = internal_breakpoint_number--;
- else
- {
- set_breakpoint_count (breakpoint_count + 1);
- b->number = breakpoint_count;
- }
- }
- static struct breakpoint *
- create_internal_breakpoint (struct gdbarch *gdbarch,
- CORE_ADDR address, enum bptype type,
- const struct breakpoint_ops *ops)
- {
- symtab_and_line sal;
- sal.pc = address;
- sal.section = find_pc_overlay (sal.pc);
- sal.pspace = current_program_space;
- breakpoint *b = set_raw_breakpoint (gdbarch, sal, type, ops);
- b->number = internal_breakpoint_number--;
- b->disposition = disp_donttouch;
- return b;
- }
- static const char *const longjmp_names[] =
- {
- "longjmp", "_longjmp", "siglongjmp", "_siglongjmp"
- };
- #define NUM_LONGJMP_NAMES ARRAY_SIZE(longjmp_names)
- /* Per-objfile data private to breakpoint.c. */
- struct breakpoint_objfile_data
- {
- /* Minimal symbol for "_ovly_debug_event" (if any). */
- struct bound_minimal_symbol overlay_msym;
- /* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any). */
- struct bound_minimal_symbol longjmp_msym[NUM_LONGJMP_NAMES];
- /* True if we have looked for longjmp probes. */
- int longjmp_searched = 0;
- /* SystemTap probe points for longjmp (if any). These are non-owning
- references. */
- std::vector<probe *> longjmp_probes;
- /* Minimal symbol for "std::terminate()" (if any). */
- struct bound_minimal_symbol terminate_msym;
- /* Minimal symbol for "_Unwind_DebugHook" (if any). */
- struct bound_minimal_symbol exception_msym;
- /* True if we have looked for exception probes. */
- int exception_searched = 0;
- /* SystemTap probe points for unwinding (if any). These are non-owning
- references. */
- std::vector<probe *> exception_probes;
- };
- static const struct objfile_key<breakpoint_objfile_data>
- breakpoint_objfile_key;
- /* Minimal symbol not found sentinel. */
- static struct minimal_symbol msym_not_found;
- /* Returns TRUE if MSYM point to the "not found" sentinel. */
- static int
- msym_not_found_p (const struct minimal_symbol *msym)
- {
- return msym == &msym_not_found;
- }
- /* Return per-objfile data needed by breakpoint.c.
- Allocate the data if necessary. */
- static struct breakpoint_objfile_data *
- get_breakpoint_objfile_data (struct objfile *objfile)
- {
- struct breakpoint_objfile_data *bp_objfile_data;
- bp_objfile_data = breakpoint_objfile_key.get (objfile);
- if (bp_objfile_data == NULL)
- bp_objfile_data = breakpoint_objfile_key.emplace (objfile);
- return bp_objfile_data;
- }
- static void
- create_overlay_event_breakpoint (void)
- {
- const char *const func_name = "_ovly_debug_event";
- for (objfile *objfile : current_program_space->objfiles ())
- {
- struct breakpoint *b;
- struct breakpoint_objfile_data *bp_objfile_data;
- CORE_ADDR addr;
- struct explicit_location explicit_loc;
- bp_objfile_data = get_breakpoint_objfile_data (objfile);
- if (msym_not_found_p (bp_objfile_data->overlay_msym.minsym))
- continue;
- if (bp_objfile_data->overlay_msym.minsym == NULL)
- {
- struct bound_minimal_symbol m;
- m = lookup_minimal_symbol_text (func_name, objfile);
- if (m.minsym == NULL)
- {
- /* Avoid future lookups in this objfile. */
- bp_objfile_data->overlay_msym.minsym = &msym_not_found;
- continue;
- }
- bp_objfile_data->overlay_msym = m;
- }
- addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym);
- b = create_internal_breakpoint (objfile->arch (), addr,
- bp_overlay_event,
- &internal_breakpoint_ops);
- initialize_explicit_location (&explicit_loc);
- explicit_loc.function_name = ASTRDUP (func_name);
- b->location = new_explicit_location (&explicit_loc);
- if (overlay_debugging == ovly_auto)
- {
- b->enable_state = bp_enabled;
- overlay_events_enabled = 1;
- }
- else
- {
- b->enable_state = bp_disabled;
- overlay_events_enabled = 0;
- }
- }
- }
- /* Install a master longjmp breakpoint for OBJFILE using a probe. Return
- true if a breakpoint was installed. */
- static bool
- create_longjmp_master_breakpoint_probe (objfile *objfile)
- {
- struct gdbarch *gdbarch = objfile->arch ();
- struct breakpoint_objfile_data *bp_objfile_data
- = get_breakpoint_objfile_data (objfile);
- if (!bp_objfile_data->longjmp_searched)
- {
- std::vector<probe *> ret
- = find_probes_in_objfile (objfile, "libc", "longjmp");
- if (!ret.empty ())
- {
- /* We are only interested in checking one element. */
- probe *p = ret[0];
- if (!p->can_evaluate_arguments ())
- {
- /* We cannot use the probe interface here,
- because it does not know how to evaluate
- arguments. */
- ret.clear ();
- }
- }
- bp_objfile_data->longjmp_probes = ret;
- bp_objfile_data->longjmp_searched = 1;
- }
- if (bp_objfile_data->longjmp_probes.empty ())
- return false;
- for (probe *p : bp_objfile_data->longjmp_probes)
- {
- struct breakpoint *b;
- b = create_internal_breakpoint (gdbarch,
- p->get_relocated_address (objfile),
- bp_longjmp_master,
- &internal_breakpoint_ops);
- b->location = new_probe_location ("-probe-stap libc:longjmp");
- b->enable_state = bp_disabled;
- }
- return true;
- }
- /* Install master longjmp breakpoints for OBJFILE using longjmp_names.
- Return true if at least one breakpoint was installed. */
- static bool
- create_longjmp_master_breakpoint_names (objfile *objfile)
- {
- struct gdbarch *gdbarch = objfile->arch ();
- if (!gdbarch_get_longjmp_target_p (gdbarch))
- return false;
- struct breakpoint_objfile_data *bp_objfile_data
- = get_breakpoint_objfile_data (objfile);
- unsigned int installed_bp = 0;
- for (int i = 0; i < NUM_LONGJMP_NAMES; i++)
- {
- struct breakpoint *b;
- const char *func_name;
- CORE_ADDR addr;
- struct explicit_location explicit_loc;
- if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
- continue;
- func_name = longjmp_names[i];
- if (bp_objfile_data->longjmp_msym[i].minsym == NULL)
- {
- struct bound_minimal_symbol m;
- m = lookup_minimal_symbol_text (func_name, objfile);
- if (m.minsym == NULL)
- {
- /* Prevent future lookups in this objfile. */
- bp_objfile_data->longjmp_msym[i].minsym = &msym_not_found;
- continue;
- }
- bp_objfile_data->longjmp_msym[i] = m;
- }
- addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
- b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
- &internal_breakpoint_ops);
- initialize_explicit_location (&explicit_loc);
- explicit_loc.function_name = ASTRDUP (func_name);
- b->location = new_explicit_location (&explicit_loc);
- b->enable_state = bp_disabled;
- installed_bp++;
- }
- return installed_bp > 0;
- }
- /* Create a master longjmp breakpoint. */
- static void
- create_longjmp_master_breakpoint (void)
- {
- scoped_restore_current_program_space restore_pspace;
- for (struct program_space *pspace : program_spaces)
- {
- set_current_program_space (pspace);
- for (objfile *obj : current_program_space->objfiles ())
- {
- /* Skip separate debug object, it's handled in the loop below. */
- if (obj->separate_debug_objfile_backlink != nullptr)
- continue;
- /* Try a probe kind breakpoint on main objfile. */
- if (create_longjmp_master_breakpoint_probe (obj))
- continue;
- /* Try longjmp_names kind breakpoints on main and separate_debug
- objfiles. */
- for (objfile *debug_objfile : obj->separate_debug_objfiles ())
- if (create_longjmp_master_breakpoint_names (debug_objfile))
- break;
- }
- }
- }
- /* Create a master std::terminate breakpoint. */
- static void
- create_std_terminate_master_breakpoint (void)
- {
- const char *const func_name = "std::terminate()";
- scoped_restore_current_program_space restore_pspace;
- for (struct program_space *pspace : program_spaces)
- {
- CORE_ADDR addr;
- set_current_program_space (pspace);
- for (objfile *objfile : current_program_space->objfiles ())
- {
- struct breakpoint *b;
- struct breakpoint_objfile_data *bp_objfile_data;
- struct explicit_location explicit_loc;
- bp_objfile_data = get_breakpoint_objfile_data (objfile);
- if (msym_not_found_p (bp_objfile_data->terminate_msym.minsym))
- continue;
- if (bp_objfile_data->terminate_msym.minsym == NULL)
- {
- struct bound_minimal_symbol m;
- m = lookup_minimal_symbol (func_name, NULL, objfile);
- if (m.minsym == NULL || (MSYMBOL_TYPE (m.minsym) != mst_text
- && MSYMBOL_TYPE (m.minsym) != mst_file_text))
- {
- /* Prevent future lookups in this objfile. */
- bp_objfile_data->terminate_msym.minsym = &msym_not_found;
- continue;
- }
- bp_objfile_data->terminate_msym = m;
- }
- addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym);
- b = create_internal_breakpoint (objfile->arch (), addr,
- bp_std_terminate_master,
- &internal_breakpoint_ops);
- initialize_explicit_location (&explicit_loc);
- explicit_loc.function_name = ASTRDUP (func_name);
- b->location = new_explicit_location (&explicit_loc);
- b->enable_state = bp_disabled;
- }
- }
- }
- /* Install a master breakpoint on the unwinder's debug hook for OBJFILE using a
- probe. Return true if a breakpoint was installed. */
- static bool
- create_exception_master_breakpoint_probe (objfile *objfile)
- {
- struct breakpoint *b;
- struct gdbarch *gdbarch;
- struct breakpoint_objfile_data *bp_objfile_data;
- bp_objfile_data = get_breakpoint_objfile_data (objfile);
- /* We prefer the SystemTap probe point if it exists. */
- if (!bp_objfile_data->exception_searched)
- {
- std::vector<probe *> ret
- = find_probes_in_objfile (objfile, "libgcc", "unwind");
- if (!ret.empty ())
- {
- /* We are only interested in checking one element. */
- probe *p = ret[0];
- if (!p->can_evaluate_arguments ())
- {
- /* We cannot use the probe interface here, because it does
- not know how to evaluate arguments. */
- ret.clear ();
- }
- }
- bp_objfile_data->exception_probes = ret;
- bp_objfile_data->exception_searched = 1;
- }
- if (bp_objfile_data->exception_probes.empty ())
- return false;
- gdbarch = objfile->arch ();
- for (probe *p : bp_objfile_data->exception_probes)
- {
- b = create_internal_breakpoint (gdbarch,
- p->get_relocated_address (objfile),
- bp_exception_master,
- &internal_breakpoint_ops);
- b->location = new_probe_location ("-probe-stap libgcc:unwind");
- b->enable_state = bp_disabled;
- }
- return true;
- }
- /* Install a master breakpoint on the unwinder's debug hook for OBJFILE using
- _Unwind_DebugHook. Return true if a breakpoint was installed. */
- static bool
- create_exception_master_breakpoint_hook (objfile *objfile)
- {
- const char *const func_name = "_Unwind_DebugHook";
- struct breakpoint *b;
- struct gdbarch *gdbarch;
- struct breakpoint_objfile_data *bp_objfile_data;
- CORE_ADDR addr;
- struct explicit_location explicit_loc;
- bp_objfile_data = get_breakpoint_objfile_data (objfile);
- if (msym_not_found_p (bp_objfile_data->exception_msym.minsym))
- return false;
- gdbarch = objfile->arch ();
- if (bp_objfile_data->exception_msym.minsym == NULL)
- {
- struct bound_minimal_symbol debug_hook;
- debug_hook = lookup_minimal_symbol (func_name, NULL, objfile);
- if (debug_hook.minsym == NULL)
- {
- bp_objfile_data->exception_msym.minsym = &msym_not_found;
- return false;
- }
- bp_objfile_data->exception_msym = debug_hook;
- }
- addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
- addr = gdbarch_convert_from_func_ptr_addr
- (gdbarch, addr, current_inferior ()->top_target ());
- b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
- &internal_breakpoint_ops);
- initialize_explicit_location (&explicit_loc);
- explicit_loc.function_name = ASTRDUP (func_name);
- b->location = new_explicit_location (&explicit_loc);
- b->enable_state = bp_disabled;
- return true;
- }
- /* Install a master breakpoint on the unwinder's debug hook. */
- static void
- create_exception_master_breakpoint (void)
- {
- for (objfile *obj : current_program_space->objfiles ())
- {
- /* Skip separate debug object. */
- if (obj->separate_debug_objfile_backlink)
- continue;
- /* Try a probe kind breakpoint. */
- if (create_exception_master_breakpoint_probe (obj))
- continue;
- /* Iterate over main and separate debug objects and try an
- _Unwind_DebugHook kind breakpoint. */
- for (objfile *debug_objfile : obj->separate_debug_objfiles ())
- if (create_exception_master_breakpoint_hook (debug_objfile))
- break;
- }
- }
- /* Does B have a location spec? */
- static int
- breakpoint_event_location_empty_p (const struct breakpoint *b)
- {
- return b->location != NULL && event_location_empty_p (b->location.get ());
- }
- void
- update_breakpoints_after_exec (void)
- {
- /* We're about to delete breakpoints from GDB's lists. If the
- INSERTED flag is true, GDB will try to lift the breakpoints by
- writing the breakpoints' "shadow contents" back into memory. The
- "shadow contents" are NOT valid after an exec, so GDB should not
- do that. Instead, the target is responsible from marking
- breakpoints out as soon as it detects an exec. We don't do that
- here instead, because there may be other attempts to delete
- breakpoints after detecting an exec and before reaching here. */
- for (bp_location *bploc : all_bp_locations ())
- if (bploc->pspace == current_program_space)
- gdb_assert (!bploc->inserted);
- for (breakpoint *b : all_breakpoints_safe ())
- {
- if (b->pspace != current_program_space)
- continue;
- /* Solib breakpoints must be explicitly reset after an exec(). */
- if (b->type == bp_shlib_event)
- {
- delete_breakpoint (b);
- continue;
- }
- /* JIT breakpoints must be explicitly reset after an exec(). */
- if (b->type == bp_jit_event)
- {
- delete_breakpoint (b);
- continue;
- }
- /* Thread event breakpoints must be set anew after an exec(),
- as must overlay event and longjmp master breakpoints. */
- if (b->type == bp_thread_event || b->type == bp_overlay_event
- || b->type == bp_longjmp_master || b->type == bp_std_terminate_master
- || b->type == bp_exception_master)
- {
- delete_breakpoint (b);
- continue;
- }
- /* Step-resume breakpoints are meaningless after an exec(). */
- if (b->type == bp_step_resume || b->type == bp_hp_step_resume)
- {
- delete_breakpoint (b);
- continue;
- }
- /* Just like single-step breakpoints. */
- if (b->type == bp_single_step)
- {
- delete_breakpoint (b);
- continue;
- }
- /* Longjmp and longjmp-resume breakpoints are also meaningless
- after an exec. */
- if (b->type == bp_longjmp || b->type == bp_longjmp_resume
- || b->type == bp_longjmp_call_dummy
- || b->type == bp_exception || b->type == bp_exception_resume)
- {
- delete_breakpoint (b);
- continue;
- }
- if (b->type == bp_catchpoint)
- {
- /* For now, none of the bp_catchpoint breakpoints need to
- do anything at this point. In the future, if some of
- the catchpoints need to something, we will need to add
- a new method, and call this method from here. */
- continue;
- }
- /* bp_finish is a special case. The only way we ought to be able
- to see one of these when an exec() has happened, is if the user
- caught a vfork, and then said "finish". Ordinarily a finish just
- carries them to the call-site of the current callee, by setting
- a temporary bp there and resuming. But in this case, the finish
- will carry them entirely through the vfork & exec.
- We don't want to allow a bp_finish to remain inserted now. But
- we can't safely delete it, 'cause finish_command has a handle to
- the bp on a bpstat, and will later want to delete it. There's a
- chance (and I've seen it happen) that if we delete the bp_finish
- here, that its storage will get reused by the time finish_command
- gets 'round to deleting the "use to be a bp_finish" breakpoint.
- We really must allow finish_command to delete a bp_finish.
- In the absence of a general solution for the "how do we know
- it's safe to delete something others may have handles to?"
- problem, what we'll do here is just uninsert the bp_finish, and
- let finish_command delete it.
- (We know the bp_finish is "doomed" in the sense that it's
- momentary, and will be deleted as soon as finish_command sees
- the inferior stopped. So it doesn't matter that the bp's
- address is probably bogus in the new a.out, unlike e.g., the
- solib breakpoints.) */
- if (b->type == bp_finish)
- {
- continue;
- }
- /* Without a symbolic address, we have little hope of the
- pre-exec() address meaning the same thing in the post-exec()
- a.out. */
- if (breakpoint_event_location_empty_p (b))
- {
- delete_breakpoint (b);
- continue;
- }
- }
- }
- int
- detach_breakpoints (ptid_t ptid)
- {
- int val = 0;
- scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
- struct inferior *inf = current_inferior ();
- if (ptid.pid () == inferior_ptid.pid ())
- error (_("Cannot detach breakpoints of inferior_ptid"));
- /* Set inferior_ptid; remove_breakpoint_1 uses this global. */
- inferior_ptid = ptid;
- for (bp_location *bl : all_bp_locations ())
- {
- if (bl->pspace != inf->pspace)
- continue;
- /* This function must physically remove breakpoints locations
- from the specified ptid, without modifying the breakpoint
- package's state. Locations of type bp_loc_other are only
- maintained at GDB side. So, there is no need to remove
- these bp_loc_other locations. Moreover, removing these
- would modify the breakpoint package's state. */
- if (bl->loc_type == bp_loc_other)
- continue;
- if (bl->inserted)
- val |= remove_breakpoint_1 (bl, DETACH_BREAKPOINT);
- }
- return val;
- }
- /* Remove the breakpoint location BL from the current address space.
- Note that this is used to detach breakpoints from a child fork.
- When we get here, the child isn't in the inferior list, and neither
- do we have objects to represent its address space --- we should
- *not* look at bl->pspace->aspace here. */
- static int
- remove_breakpoint_1 (struct bp_location *bl, enum remove_bp_reason reason)
- {
- int val;
- /* BL is never in moribund_locations by our callers. */
- gdb_assert (bl->owner != NULL);
- /* The type of none suggests that owner is actually deleted.
- This should not ever happen. */
- gdb_assert (bl->owner->type != bp_none);
- if (bl->loc_type == bp_loc_software_breakpoint
- || bl->loc_type == bp_loc_hardware_breakpoint)
- {
- /* "Normal" instruction breakpoint: either the standard
- trap-instruction bp (bp_breakpoint), or a
- bp_hardware_breakpoint. */
- /* First check to see if we have to handle an overlay. */
- if (overlay_debugging == ovly_off
- || bl->section == NULL
- || !(section_is_overlay (bl->section)))
- {
- /* No overlay handling: just remove the breakpoint. */
- /* If we're trying to uninsert a memory breakpoint that we
- know is set in a dynamic object that is marked
- shlib_disabled, then either the dynamic object was
- removed with "remove-symbol-file" or with
- "nosharedlibrary". In the former case, we don't know
- whether another dynamic object might have loaded over the
- breakpoint's address -- the user might well let us know
- about it next with add-symbol-file (the whole point of
- add-symbol-file is letting the user manually maintain a
- list of dynamically loaded objects). If we have the
- breakpoint's shadow memory, that is, this is a software
- breakpoint managed by GDB, check whether the breakpoint
- is still inserted in memory, to avoid overwriting wrong
- code with stale saved shadow contents. Note that HW
- breakpoints don't have shadow memory, as they're
- implemented using a mechanism that is not dependent on
- being able to modify the target's memory, and as such
- they should always be removed. */
- if (bl->shlib_disabled
- && bl->target_info.shadow_len != 0
- && !memory_validate_breakpoint (bl->gdbarch, &bl->target_info))
- val = 0;
- else
- val = bl->owner->ops->remove_location (bl, reason);
- }
- else
- {
- /* This breakpoint is in an overlay section.
- Did we set a breakpoint at the LMA? */
- if (!overlay_events_enabled)
- {
- /* Yes -- overlay event support is not active, so we
- should have set a breakpoint at the LMA. Remove it.
- */
- /* Ignore any failures: if the LMA is in ROM, we will
- have already warned when we failed to insert it. */
- if (bl->loc_type == bp_loc_hardware_breakpoint)
- target_remove_hw_breakpoint (bl->gdbarch,
- &bl->overlay_target_info);
- else
- target_remove_breakpoint (bl->gdbarch,
- &bl->overlay_target_info,
- reason);
- }
- /* Did we set a breakpoint at the VMA?
- If so, we will have marked the breakpoint 'inserted'. */
- if (bl->inserted)
- {
- /* Yes -- remove it. Previously we did not bother to
- remove the breakpoint if the section had been
- unmapped, but let's not rely on that being safe. We
- don't know what the overlay manager might do. */
- /* However, we should remove *software* breakpoints only
- if the section is still mapped, or else we overwrite
- wrong code with the saved shadow contents. */
- if (bl->loc_type == bp_loc_hardware_breakpoint
- || section_is_mapped (bl->section))
- val = bl->owner->ops->remove_location (bl, reason);
- else
- val = 0;
- }
- else
- {
- /* No -- not inserted, so no need to remove. No error. */
- val = 0;
- }
- }
- /* In some cases, we might not be able to remove a breakpoint in
- a shared library that has already been removed, but we have
- not yet processed the shlib unload event. Similarly for an
- unloaded add-symbol-file object - the user might not yet have
- had the chance to remove-symbol-file it. shlib_disabled will
- be set if the library/object has already been removed, but
- the breakpoint hasn't been uninserted yet, e.g., after
- "nosharedlibrary" or "remove-symbol-file" with breakpoints
- always-inserted mode. */
- if (val
- && (bl->loc_type == bp_loc_software_breakpoint
- && (bl->shlib_disabled
- || solib_name_from_address (bl->pspace, bl->address)
- || shared_objfile_contains_address_p (bl->pspace,
- bl->address))))
- val = 0;
- if (val)
- return val;
- bl->inserted = (reason == DETACH_BREAKPOINT);
- }
- else if (bl->loc_type == bp_loc_hardware_watchpoint)
- {
- gdb_assert (bl->owner->ops != NULL
- && bl->owner->ops->remove_location != NULL);
- bl->inserted = (reason == DETACH_BREAKPOINT);
- bl->owner->ops->remove_location (bl, reason);
- /* Failure to remove any of the hardware watchpoints comes here. */
- if (reason == REMOVE_BREAKPOINT && bl->inserted)
- warning (_("Could not remove hardware watchpoint %d."),
- bl->owner->number);
- }
- else if (bl->owner->type == bp_catchpoint
- && breakpoint_enabled (bl->owner)
- && !bl->duplicate)
- {
- gdb_assert (bl->owner->ops != NULL
- && bl->owner->ops->remove_location != NULL);
- val = bl->owner->ops->remove_location (bl, reason);
- if (val)
- return val;
- bl->inserted = (reason == DETACH_BREAKPOINT);
- }
- return 0;
- }
- static int
- remove_breakpoint (struct bp_location *bl)
- {
- /* BL is never in moribund_locations by our callers. */
- gdb_assert (bl->owner != NULL);
- /* The type of none suggests that owner is actually deleted.
- This should not ever happen. */
- gdb_assert (bl->owner->type != bp_none);
- scoped_restore_current_pspace_and_thread restore_pspace_thread;
- switch_to_program_space_and_thread (bl->pspace);
- return remove_breakpoint_1 (bl, REMOVE_BREAKPOINT);
- }
- /* Clear the "inserted" flag in all breakpoints. */
- void
- mark_breakpoints_out (void)
- {
- for (bp_location *bl : all_bp_locations ())
- if (bl->pspace == current_program_space)
- bl->inserted = 0;
- }
- /* Clear the "inserted" flag in all breakpoints and delete any
- breakpoints which should go away between runs of the program.
- Plus other such housekeeping that has to be done for breakpoints
- between runs.
- Note: this function gets called at the end of a run (by
- generic_mourn_inferior) and when a run begins (by
- init_wait_for_inferior). */
- void
- breakpoint_init_inferior (enum inf_context context)
- {
- struct program_space *pspace = current_program_space;
- /* If breakpoint locations are shared across processes, then there's
- nothing to do. */
- if (gdbarch_has_global_breakpoints (target_gdbarch ()))
- return;
- mark_breakpoints_out ();
- for (breakpoint *b : all_breakpoints_safe ())
- {
- if (b->loc && b->loc->pspace != pspace)
- continue;
- switch (b->type)
- {
- case bp_call_dummy:
- case bp_longjmp_call_dummy:
- /* If the call dummy breakpoint is at the entry point it will
- cause problems when the inferior is rerun, so we better get
- rid of it. */
- case bp_watchpoint_scope:
- /* Also get rid of scope breakpoints. */
- case bp_shlib_event:
- /* Also remove solib event breakpoints. Their addresses may
- have changed since the last time we ran the program.
- Actually we may now be debugging against different target;
- and so the solib backend that installed this breakpoint may
- not be used in by the target. E.g.,
- (gdb) file prog-linux
- (gdb) run # native linux target
- ...
- (gdb) kill
- (gdb) file prog-win.exe
- (gdb) tar rem :9999 # remote Windows gdbserver.
- */
- case bp_step_resume:
- /* Also remove step-resume breakpoints. */
- case bp_single_step:
- /* Also remove single-step breakpoints. */
- delete_breakpoint (b);
- break;
- case bp_watchpoint:
- case bp_hardware_watchpoint:
- case bp_read_watchpoint:
- case bp_access_watchpoint:
- {
- struct watchpoint *w = (struct watchpoint *) b;
- /* Likewise for watchpoints on local expressions. */
- if (w->exp_valid_block != NULL)
- delete_breakpoint (b);
- else
- {
- /* Get rid of existing locations, which are no longer
- valid. New ones will be created in
- update_watchpoint, when the inferior is restarted.
- The next update_global_location_list call will
- garbage collect them. */
- b->loc = NULL;
- if (context == inf_starting)
- {
- /* Reset val field to force reread of starting value in
- insert_breakpoints. */
- w->val.reset (nullptr);
- w->val_valid = false;
- }
- }
- }
- break;
- default:
- break;
- }
- }
- /* Get rid of the moribund locations. */
- for (bp_location *bl : moribund_locations)
- decref_bp_location (&bl);
- moribund_locations.clear ();
- }
- /* These functions concern about actual breakpoints inserted in the
- target --- to e.g. check if we need to do decr_pc adjustment or if
- we need to hop over the bkpt --- so we check for address space
- match, not program space. */
- /* breakpoint_here_p (PC) returns non-zero if an enabled breakpoint
- exists at PC. It returns ordinary_breakpoint_here if it's an
- ordinary breakpoint, or permanent_breakpoint_here if it's a
- permanent breakpoint.
- - When continuing from a location with an ordinary breakpoint, we
- actually single step once before calling insert_breakpoints.
- - When continuing from a location with a permanent breakpoint, we
- need to use the `SKIP_PERMANENT_BREAKPOINT' macro, provided by
- the target, to advance the PC past the breakpoint. */
- enum breakpoint_here
- breakpoint_here_p (const address_space *aspace, CORE_ADDR pc)
- {
- int any_breakpoint_here = 0;
- for (bp_location *bl : all_bp_locations ())
- {
- if (bl->loc_type != bp_loc_software_breakpoint
- && bl->loc_type != bp_loc_hardware_breakpoint)
- continue;
- /* ALL_BP_LOCATIONS bp_location has BL->OWNER always non-NULL. */
- if ((breakpoint_enabled (bl->owner)
- || bl->permanent)
- && breakpoint_location_address_match (bl, aspace, pc))
- {
- if (overlay_debugging
- && section_is_overlay (bl->section)
- && !section_is_mapped (bl->section))
- continue; /* unmapped overlay -- can't be a match */
- else if (bl->permanent)
- return permanent_breakpoint_here;
- else
- any_breakpoint_here = 1;
- }
- }
- return any_breakpoint_here ? ordinary_breakpoint_here : no_breakpoint_here;
- }
- /* See breakpoint.h. */
- int
- breakpoint_in_range_p (const address_space *aspace,
- CORE_ADDR addr, ULONGEST len)
- {
- for (bp_location *bl : all_bp_locations ())
- {
- if (bl->loc_type != bp_loc_software_breakpoint
- && bl->loc_type != bp_loc_hardware_breakpoint)
- continue;
- if ((breakpoint_enabled (bl->owner)
- || bl->permanent)
- && breakpoint_location_address_range_overlap (bl, aspace,
- addr, len))
- {
- if (overlay_debugging
- && section_is_overlay (bl->section)
- && !section_is_mapped (bl->section))
- {
- /* Unmapped overlay -- can't be a match. */
- continue;
- }
- return 1;
- }
- }
- return 0;
- }
- /* Return true if there's a moribund breakpoint at PC. */
- int
- moribund_breakpoint_here_p (const address_space *aspace, CORE_ADDR pc)
- {
- for (bp_location *loc : moribund_locations)
- if (breakpoint_location_address_match (loc, aspace, pc))
- return 1;
- return 0;
- }
- /* Returns non-zero iff BL is inserted at PC, in address space
- ASPACE. */
- static int
- bp_location_inserted_here_p (struct bp_location *bl,
- const address_space *aspace, CORE_ADDR pc)
- {
- if (bl->inserted
- && breakpoint_address_match (bl->pspace->aspace, bl->address,
- aspace, pc))
- {
- if (overlay_debugging
- && section_is_overlay (bl->section)
- && !section_is_mapped (bl->section))
- return 0; /* unmapped overlay -- can't be a match */
- else
- return 1;
- }
- return 0;
- }
- /* Returns non-zero iff there's a breakpoint inserted at PC. */
- int
- breakpoint_inserted_here_p (const address_space *aspace, CORE_ADDR pc)
- {
- for (bp_location *bl : all_bp_locations_at_addr (pc))
- {
- if (bl->loc_type != bp_loc_software_breakpoint
- && bl->loc_type != bp_loc_hardware_breakpoint)
- continue;
- if (bp_location_inserted_here_p (bl, aspace, pc))
- return 1;
- }
- return 0;
- }
- /* This function returns non-zero iff there is a software breakpoint
- inserted at PC. */
- int
- software_breakpoint_inserted_here_p (const address_space *aspace,
- CORE_ADDR pc)
- {
- for (bp_location *bl : all_bp_locations_at_addr (pc))
- {
- if (bl->loc_type != bp_loc_software_breakpoint)
- continue;
- if (bp_location_inserted_here_p (bl, aspace, pc))
- return 1;
- }
- return 0;
- }
- /* See breakpoint.h. */
- int
- hardware_breakpoint_inserted_here_p (const address_space *aspace,
- CORE_ADDR pc)
- {
- for (bp_location *bl : all_bp_locations_at_addr (pc))
- {
- if (bl->loc_type != bp_loc_hardware_breakpoint)
- continue;
- if (bp_location_inserted_here_p (bl, aspace, pc))
- return 1;
- }
- return 0;
- }
- int
- hardware_watchpoint_inserted_in_range (const address_space *aspace,
- CORE_ADDR addr, ULONGEST len)
- {
- for (breakpoint *bpt : all_breakpoints ())
- {
- if (bpt->type != bp_hardware_watchpoint
- && bpt->type != bp_access_watchpoint)
- continue;
- if (!breakpoint_enabled (bpt))
- continue;
- for (bp_location *loc : bpt->locations ())
- if (loc->pspace->aspace == aspace && loc->inserted)
- {
- CORE_ADDR l, h;
- /* Check for intersection. */
- l = std::max<CORE_ADDR> (loc->address, addr);
- h = std::min<CORE_ADDR> (loc->address + loc->length, addr + len);
- if (l < h)
- return 1;
- }
- }
- return 0;
- }
- /* See breakpoint.h. */
- bool
- is_catchpoint (struct breakpoint *b)
- {
- return (b->type == bp_catchpoint);
- }
- /* Clear a bpstat so that it says we are not at any breakpoint.
- Also free any storage that is part of a bpstat. */
- void
- bpstat_clear (bpstat **bsp)
- {
- bpstat *p;
- bpstat *q;
- if (bsp == 0)
- return;
- p = *bsp;
- while (p != NULL)
- {
- q = p->next;
- delete p;
- p = q;
- }
- *bsp = NULL;
- }
- bpstat::bpstat (const bpstat &other)
- : next (NULL),
- bp_location_at (other.bp_location_at),
- breakpoint_at (other.breakpoint_at),
- commands (other.commands),
- print (other.print),
- stop (other.stop),
- print_it (other.print_it)
- {
- if (other.old_val != NULL)
- old_val = release_value (value_copy (other.old_val.get ()));
- }
- /* Return a copy of a bpstat. Like "bs1 = bs2" but all storage that
- is part of the bpstat is copied as well. */
- bpstat *
- bpstat_copy (bpstat *bs)
- {
- bpstat *p = nullptr;
- bpstat *tmp;
- bpstat *retval = nullptr;
- if (bs == NULL)
- return bs;
- for (; bs != NULL; bs = bs->next)
- {
- tmp = new bpstat (*bs);
- if (p == NULL)
- /* This is the first thing in the chain. */
- retval = tmp;
- else
- p->next = tmp;
- p = tmp;
- }
- p->next = NULL;
- return retval;
- }
- /* Find the bpstat associated with this breakpoint. */
- bpstat *
- bpstat_find_breakpoint (bpstat *bsp, struct breakpoint *breakpoint)
- {
- if (bsp == NULL)
- return NULL;
- for (; bsp != NULL; bsp = bsp->next)
- {
- if (bsp->breakpoint_at == breakpoint)
- return bsp;
- }
- return NULL;
- }
- /* See breakpoint.h. */
- bool
- bpstat_explains_signal (bpstat *bsp, enum gdb_signal sig)
- {
- for (; bsp != NULL; bsp = bsp->next)
- {
- if (bsp->breakpoint_at == NULL)
- {
- /* A moribund location can never explain a signal other than
- GDB_SIGNAL_TRAP. */
- if (sig == GDB_SIGNAL_TRAP)
- return true;
- }
- else
- {
- if (bsp->breakpoint_at->ops->explains_signal (bsp->breakpoint_at,
- sig))
- return true;
- }
- }
- return false;
- }
- /* Put in *NUM the breakpoint number of the first breakpoint we are
- stopped at. *BSP upon return is a bpstat which points to the
- remaining breakpoints stopped at (but which is not guaranteed to be
- good for anything but further calls to bpstat_num).
- Return 0 if passed a bpstat which does not indicate any breakpoints.
- Return -1 if stopped at a breakpoint that has been deleted since
- we set it.
- Return 1 otherwise. */
- int
- bpstat_num (bpstat **bsp, int *num)
- {
- struct breakpoint *b;
- if ((*bsp) == NULL)
- return 0; /* No more breakpoint values */
- /* We assume we'll never have several bpstats that correspond to a
- single breakpoint -- otherwise, this function might return the
- same number more than once and this will look ugly. */
- b = (*bsp)->breakpoint_at;
- *bsp = (*bsp)->next;
- if (b == NULL)
- return -1; /* breakpoint that's been deleted since */
- *num = b->number; /* We have its number */
- return 1;
- }
- /* See breakpoint.h. */
- void
- bpstat_clear_actions (void)
- {
- bpstat *bs;
- if (inferior_ptid == null_ptid)
- return;
- thread_info *tp = inferior_thread ();
- for (bs = tp->control.stop_bpstat; bs != NULL; bs = bs->next)
- {
- bs->commands = NULL;
- bs->old_val.reset (nullptr);
- }
- }
- /* Called when a command is about to proceed the inferior. */
- static void
- breakpoint_about_to_proceed (void)
- {
- if (inferior_ptid != null_ptid)
- {
- struct thread_info *tp = inferior_thread ();
- /* Allow inferior function calls in breakpoint commands to not
- interrupt the command list. When the call finishes
- successfully, the inferior will be standing at the same
- breakpoint as if nothing happened. */
- if (tp->control.in_infcall)
- return;
- }
- breakpoint_proceeded = 1;
- }
- /* Return non-zero iff CMD as the first line of a command sequence is `silent'
- or its equivalent. */
- static int
- command_line_is_silent (struct command_line *cmd)
- {
- return cmd && (strcmp ("silent", cmd->line) == 0);
- }
- /* Execute all the commands associated with all the breakpoints at
- this location. Any of these commands could cause the process to
- proceed beyond this point, etc. We look out for such changes by
- checking the global "breakpoint_proceeded" after each command.
- Returns true if a breakpoint command resumed the inferior. In that
- case, it is the caller's responsibility to recall it again with the
- bpstat of the current thread. */
- static int
- bpstat_do_actions_1 (bpstat **bsp)
- {
- bpstat *bs;
- int again = 0;
- /* Avoid endless recursion if a `source' command is contained
- in bs->commands. */
- if (executing_breakpoint_commands)
- return 0;
- scoped_restore save_executing
- = make_scoped_restore (&executing_breakpoint_commands, 1);
- scoped_restore preventer = prevent_dont_repeat ();
- /* This pointer will iterate over the list of bpstat's. */
- bs = *bsp;
- breakpoint_proceeded = 0;
- for (; bs != NULL; bs = bs->next)
- {
- struct command_line *cmd = NULL;
- /* Take ownership of the BSP's command tree, if it has one.
- The command tree could legitimately contain commands like
- 'step' and 'next', which call clear_proceed_status, which
- frees stop_bpstat's command tree. To make sure this doesn't
- free the tree we're executing out from under us, we need to
- take ownership of the tree ourselves. Since a given bpstat's
- commands are only executed once, we don't need to copy it; we
- can clear the pointer in the bpstat, and make sure we free
- the tree when we're done. */
- counted_command_line ccmd = bs->commands;
- bs->commands = NULL;
- if (ccmd != NULL)
- cmd = ccmd.get ();
- if (command_line_is_silent (cmd))
- {
- /* The action has been already done by bpstat_stop_status. */
- cmd = cmd->next;
- }
- while (cmd != NULL)
- {
- execute_control_command (cmd);
- if (breakpoint_proceeded)
- break;
- else
- cmd = cmd->next;
- }
- if (breakpoint_proceeded)
- {
- if (current_ui->async)
- /* If we are in async mode, then the target might be still
- running, not stopped at any breakpoint, so nothing for
- us to do here -- just return to the event loop. */
- ;
- else
- /* In sync mode, when execute_control_command returns
- we're already standing on the next breakpoint.
- Breakpoint commands for that stop were not run, since
- execute_command does not run breakpoint commands --
- only command_line_handler does, but that one is not
- involved in execution of breakpoint commands. So, we
- can now execute breakpoint commands. It should be
- noted that making execute_command do bpstat actions is
- not an option -- in this case we'll have recursive
- invocation of bpstat for each breakpoint with a
- command, and can easily blow up GDB stack. Instead, we
- return true, which will trigger the caller to recall us
- with the new stop_bpstat. */
- again = 1;
- break;
- }
- }
- return again;
- }
- /* Helper for bpstat_do_actions. Get the current thread, if there's
- one, is alive and has execution. Return NULL otherwise. */
- static thread_info *
- get_bpstat_thread ()
- {
- if (inferior_ptid == null_ptid || !target_has_execution ())
- return NULL;
- thread_info *tp = inferior_thread ();
- if (tp->state == THREAD_EXITED || tp->executing ())
- return NULL;
- return tp;
- }
- void
- bpstat_do_actions (void)
- {
- auto cleanup_if_error = make_scope_exit (bpstat_clear_actions);
- thread_info *tp;
- /* Do any commands attached to breakpoint we are stopped at. */
- while ((tp = get_bpstat_thread ()) != NULL)
- {
- /* Since in sync mode, bpstat_do_actions may resume the
- inferior, and only return when it is stopped at the next
- breakpoint, we keep doing breakpoint actions until it returns
- false to indicate the inferior was not resumed. */
- if (!bpstat_do_actions_1 (&tp->control.stop_bpstat))
- break;
- }
- cleanup_if_error.release ();
- }
- /* Print out the (old or new) value associated with a watchpoint. */
- static void
- watchpoint_value_print (struct value *val, struct ui_file *stream)
- {
- if (val == NULL)
- fprintf_styled (stream, metadata_style.style (), _("<unreadable>"));
- else
- {
- struct value_print_options opts;
- get_user_print_options (&opts);
- value_print (val, stream, &opts);
- }
- }
- /* Print the "Thread ID hit" part of "Thread ID hit Breakpoint N" if
- debugging multiple threads. */
- void
- maybe_print_thread_hit_breakpoint (struct ui_out *uiout)
- {
- if (uiout->is_mi_like_p ())
- return;
- uiout->text ("\n");
- if (show_thread_that_caused_stop ())
- {
- struct thread_info *thr = inferior_thread ();
- uiout->text ("Thread ");
- uiout->field_string ("thread-id", print_thread_id (thr));
- const char *name = thread_name (thr);
- if (name != NULL)
- {
- uiout->text (" \"");
- uiout->field_string ("name", name);
- uiout->text ("\"");
- }
- uiout->text (" hit ");
- }
- }
- /* Generic routine for printing messages indicating why we
- stopped. The behavior of this function depends on the value
- 'print_it' in the bpstat structure. Under some circumstances we
- may decide not to print anything here and delegate the task to
- normal_stop(). */
- static enum print_stop_action
- print_bp_stop_message (bpstat *bs)
- {
- switch (bs->print_it)
- {
- case print_it_noop:
- /* Nothing should be printed for this bpstat entry. */
- return PRINT_UNKNOWN;
- break;
- case print_it_done:
- /* We still want to print the frame, but we already printed the
- relevant messages. */
- return PRINT_SRC_AND_LOC;
- break;
- case print_it_normal:
- {
- struct breakpoint *b = bs->breakpoint_at;
- /* bs->breakpoint_at can be NULL if it was a momentary breakpoint
- which has since been deleted. */
- if (b == NULL)
- return PRINT_UNKNOWN;
- /* Normal case. Call the breakpoint's print_it method. */
- return b->ops->print_it (bs);
- }
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("print_bp_stop_message: unrecognized enum value"));
- break;
- }
- }
- /* A helper function that prints a shared library stopped event. */
- static void
- print_solib_event (int is_catchpoint)
- {
- bool any_deleted = !current_program_space->deleted_solibs.empty ();
- bool any_added = !current_program_space->added_solibs.empty ();
- if (!is_catchpoint)
- {
- if (any_added || any_deleted)
- current_uiout->text (_("Stopped due to shared library event:\n"));
- else
- current_uiout->text (_("Stopped due to shared library event (no "
- "libraries added or removed)\n"));
- }
- if (current_uiout->is_mi_like_p ())
- current_uiout->field_string ("reason",
- async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT));
- if (any_deleted)
- {
- current_uiout->text (_(" Inferior unloaded "));
- ui_out_emit_list list_emitter (current_uiout, "removed");
- for (int ix = 0; ix < current_program_space->deleted_solibs.size (); ix++)
- {
- const std::string &name = current_program_space->deleted_solibs[ix];
- if (ix > 0)
- current_uiout->text (" ");
- current_uiout->field_string ("library", name);
- current_uiout->text ("\n");
- }
- }
- if (any_added)
- {
- current_uiout->text (_(" Inferior loaded "));
- ui_out_emit_list list_emitter (current_uiout, "added");
- bool first = true;
- for (so_list *iter : current_program_space->added_solibs)
- {
- if (!first)
- current_uiout->text (" ");
- first = false;
- current_uiout->field_string ("library", iter->so_name);
- current_uiout->text ("\n");
- }
- }
- }
- /* Print a message indicating what happened. This is called from
- normal_stop(). The input to this routine is the head of the bpstat
- list - a list of the eventpoints that caused this stop. KIND is
- the target_waitkind for the stopping event. This
- routine calls the generic print routine for printing a message
- about reasons for stopping. This will print (for example) the
- "Breakpoint n," part of the output. The return value of this
- routine is one of:
- PRINT_UNKNOWN: Means we printed nothing.
- PRINT_SRC_AND_LOC: Means we printed something, and expect subsequent
- code to print the location. An example is
- "Breakpoint 1, " which should be followed by
- the location.
- PRINT_SRC_ONLY: Means we printed something, but there is no need
- to also print the location part of the message.
- An example is the catch/throw messages, which
- don't require a location appended to the end.
- PRINT_NOTHING: We have done some printing and we don't need any
- further info to be printed. */
- enum print_stop_action
- bpstat_print (bpstat *bs, int kind)
- {
- enum print_stop_action val;
- /* Maybe another breakpoint in the chain caused us to stop.
- (Currently all watchpoints go on the bpstat whether hit or not.
- That probably could (should) be changed, provided care is taken
- with respect to bpstat_explains_signal). */
- for (; bs; bs = bs->next)
- {
- val = print_bp_stop_message (bs);
- if (val == PRINT_SRC_ONLY
- || val == PRINT_SRC_AND_LOC
- || val == PRINT_NOTHING)
- return val;
- }
- /* If we had hit a shared library event breakpoint,
- print_bp_stop_message would print out this message. If we hit an
- OS-level shared library event, do the same thing. */
- if (kind == TARGET_WAITKIND_LOADED)
- {
- print_solib_event (0);
- return PRINT_NOTHING;
- }
- /* We reached the end of the chain, or we got a null BS to start
- with and nothing was printed. */
- return PRINT_UNKNOWN;
- }
- /* Evaluate the boolean expression EXP and return the result. */
- static bool
- breakpoint_cond_eval (expression *exp)
- {
- struct value *mark = value_mark ();
- bool res = value_true (evaluate_expression (exp));
- value_free_to_mark (mark);
- return res;
- }
- /* Allocate a new bpstat. Link it to the FIFO list by BS_LINK_POINTER. */
- bpstat::bpstat (struct bp_location *bl, bpstat ***bs_link_pointer)
- : next (NULL),
- bp_location_at (bp_location_ref_ptr::new_reference (bl)),
- breakpoint_at (bl->owner),
- commands (NULL),
- print (0),
- stop (0),
- print_it (print_it_normal)
- {
- **bs_link_pointer = this;
- *bs_link_pointer = &next;
- }
- bpstat::bpstat ()
- : next (NULL),
- breakpoint_at (NULL),
- commands (NULL),
- print (0),
- stop (0),
- print_it (print_it_normal)
- {
- }
- /* The target has stopped with waitstatus WS. Check if any hardware
- watchpoints have triggered, according to the target. */
- int
- watchpoints_triggered (const target_waitstatus &ws)
- {
- bool stopped_by_watchpoint = target_stopped_by_watchpoint ();
- CORE_ADDR addr;
- if (!stopped_by_watchpoint)
- {
- /* We were not stopped by a watchpoint. Mark all watchpoints
- as not triggered. */
- for (breakpoint *b : all_breakpoints ())
- if (is_hardware_watchpoint (b))
- {
- struct watchpoint *w = (struct watchpoint *) b;
- w->watchpoint_triggered = watch_triggered_no;
- }
- return 0;
- }
- if (!target_stopped_data_address (current_inferior ()->top_target (), &addr))
- {
- /* We were stopped by a watchpoint, but we don't know where.
- Mark all watchpoints as unknown. */
- for (breakpoint *b : all_breakpoints ())
- if (is_hardware_watchpoint (b))
- {
- struct watchpoint *w = (struct watchpoint *) b;
- w->watchpoint_triggered = watch_triggered_unknown;
- }
- return 1;
- }
- /* The target could report the data address. Mark watchpoints
- affected by this data address as triggered, and all others as not
- triggered. */
- for (breakpoint *b : all_breakpoints ())
- if (is_hardware_watchpoint (b))
- {
- struct watchpoint *w = (struct watchpoint *) b;
- w->watchpoint_triggered = watch_triggered_no;
- for (bp_location *loc : b->locations ())
- {
- if (is_masked_watchpoint (b))
- {
- CORE_ADDR newaddr = addr & w->hw_wp_mask;
- CORE_ADDR start = loc->address & w->hw_wp_mask;
- if (newaddr == start)
- {
- w->watchpoint_triggered = watch_triggered_yes;
- break;
- }
- }
- /* Exact match not required. Within range is sufficient. */
- else if (target_watchpoint_addr_within_range
- (current_inferior ()->top_target (), addr, loc->address,
- loc->length))
- {
- w->watchpoint_triggered = watch_triggered_yes;
- break;
- }
- }
- }
- return 1;
- }
- /* Possible return values for watchpoint_check. */
- enum wp_check_result
- {
- /* The watchpoint has been deleted. */
- WP_DELETED = 1,
- /* The value has changed. */
- WP_VALUE_CHANGED = 2,
- /* The value has not changed. */
- WP_VALUE_NOT_CHANGED = 3,
- /* Ignore this watchpoint, no matter if the value changed or not. */
- WP_IGNORE = 4,
- };
- #define BP_TEMPFLAG 1
- #define BP_HARDWAREFLAG 2
- /* Evaluate watchpoint condition expression and check if its value
- changed. */
- static wp_check_result
- watchpoint_check (bpstat *bs)
- {
- struct watchpoint *b;
- struct frame_info *fr;
- int within_current_scope;
- /* BS is built from an existing struct breakpoint. */
- gdb_assert (bs->breakpoint_at != NULL);
- b = (struct watchpoint *) bs->breakpoint_at;
- /* If this is a local watchpoint, we only want to check if the
- watchpoint frame is in scope if the current thread is the thread
- that was used to create the watchpoint. */
- if (!watchpoint_in_thread_scope (b))
- return WP_IGNORE;
- if (b->exp_valid_block == NULL)
- within_current_scope = 1;
- else
- {
- struct frame_info *frame = get_current_frame ();
- struct gdbarch *frame_arch = get_frame_arch (frame);
- CORE_ADDR frame_pc = get_frame_pc (frame);
- /* stack_frame_destroyed_p() returns a non-zero value if we're
- still in the function but the stack frame has already been
- invalidated. Since we can't rely on the values of local
- variables after the stack has been destroyed, we are treating
- the watchpoint in that state as `not changed' without further
- checking. Don't mark watchpoints as changed if the current
- frame is in an epilogue - even if they are in some other
- frame, our view of the stack is likely to be wrong and
- frame_find_by_id could error out. */
- if (gdbarch_stack_frame_destroyed_p (frame_arch, frame_pc))
- return WP_IGNORE;
- fr = frame_find_by_id (b->watchpoint_frame);
- within_current_scope = (fr != NULL);
- /* If we've gotten confused in the unwinder, we might have
- returned a frame that can't describe this variable. */
- if (within_current_scope)
- {
- struct symbol *function;
- function = get_frame_function (fr);
- if (function == NULL
- || !contained_in (b->exp_valid_block,
- SYMBOL_BLOCK_VALUE (function)))
- within_current_scope = 0;
- }
- if (within_current_scope)
- /* If we end up stopping, the current frame will get selected
- in normal_stop. So this call to select_frame won't affect
- the user. */
- select_frame (fr);
- }
- if (within_current_scope)
- {
- /* We use value_{,free_to_}mark because it could be a *long*
- time before we return to the command level and call
- free_all_values. We can't call free_all_values because we
- might be in the middle of evaluating a function call. */
- struct value *mark;
- struct value *new_val;
- if (is_masked_watchpoint (b))
- /* Since we don't know the exact trigger address (from
- stopped_data_address), just tell the user we've triggered
- a mask watchpoint. */
- return WP_VALUE_CHANGED;
- mark = value_mark ();
- fetch_subexp_value (b->exp.get (), b->exp->op.get (), &new_val,
- NULL, NULL, false);
- if (b->val_bitsize != 0)
- new_val = extract_bitfield_from_watchpoint_value (b, new_val);
- /* We use value_equal_contents instead of value_equal because
- the latter coerces an array to a pointer, thus comparing just
- the address of the array instead of its contents. This is
- not what we want. */
- if ((b->val != NULL) != (new_val != NULL)
- || (b->val != NULL && !value_equal_contents (b->val.get (),
- new_val)))
- {
- bs->old_val = b->val;
- b->val = release_value (new_val);
- b->val_valid = true;
- if (new_val != NULL)
- value_free_to_mark (mark);
- return WP_VALUE_CHANGED;
- }
- else
- {
- /* Nothing changed. */
- value_free_to_mark (mark);
- return WP_VALUE_NOT_CHANGED;
- }
- }
- else
- {
- /* This seems like the only logical thing to do because
- if we temporarily ignored the watchpoint, then when
- we reenter the block in which it is valid it contains
- garbage (in the case of a function, it may have two
- garbage values, one before and one after the prologue).
- So we can't even detect the first assignment to it and
- watch after that (since the garbage may or may not equal
- the first value assigned). */
- /* We print all the stop information in
- breakpoint_ops->print_it, but in this case, by the time we
- call breakpoint_ops->print_it this bp will be deleted
- already. So we have no choice but print the information
- here. */
- SWITCH_THRU_ALL_UIS ()
- {
- struct ui_out *uiout = current_uiout;
- if (uiout->is_mi_like_p ())
- uiout->field_string
- ("reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE));
- uiout->message ("\nWatchpoint %pF deleted because the program has "
- "left the block in\n"
- "which its expression is valid.\n",
- signed_field ("wpnum", b->number));
- }
- /* Make sure the watchpoint's commands aren't executed. */
- b->commands = NULL;
- watchpoint_del_at_next_stop (b);
- return WP_DELETED;
- }
- }
- /* Return true if it looks like target has stopped due to hitting
- breakpoint location BL. This function does not check if we should
- stop, only if BL explains the stop. */
- static int
- bpstat_check_location (const struct bp_location *bl,
- const address_space *aspace, CORE_ADDR bp_addr,
- const target_waitstatus &ws)
- {
- struct breakpoint *b = bl->owner;
- /* BL is from an existing breakpoint. */
- gdb_assert (b != NULL);
- return b->ops->breakpoint_hit (bl, aspace, bp_addr, ws);
- }
- /* Determine if the watched values have actually changed, and we
- should stop. If not, set BS->stop to 0. */
- static void
- bpstat_check_watchpoint (bpstat *bs)
- {
- const struct bp_location *bl;
- struct watchpoint *b;
- /* BS is built for existing struct breakpoint. */
- bl = bs->bp_location_at.get ();
- gdb_assert (bl != NULL);
- b = (struct watchpoint *) bs->breakpoint_at;
- gdb_assert (b != NULL);
- {
- int must_check_value = 0;
-
- if (b->type == bp_watchpoint)
- /* For a software watchpoint, we must always check the
- watched value. */
- must_check_value = 1;
- else if (b->watchpoint_triggered == watch_triggered_yes)
- /* We have a hardware watchpoint (read, write, or access)
- and the target earlier reported an address watched by
- this watchpoint. */
- must_check_value = 1;
- else if (b->watchpoint_triggered == watch_triggered_unknown
- && b->type == bp_hardware_watchpoint)
- /* We were stopped by a hardware watchpoint, but the target could
- not report the data address. We must check the watchpoint's
- value. Access and read watchpoints are out of luck; without
- a data address, we can't figure it out. */
- must_check_value = 1;
- if (must_check_value)
- {
- wp_check_result e;
- try
- {
- e = watchpoint_check (bs);
- }
- catch (const gdb_exception &ex)
- {
- exception_fprintf (gdb_stderr, ex,
- "Error evaluating expression "
- "for watchpoint %d\n",
- b->number);
- SWITCH_THRU_ALL_UIS ()
- {
- gdb_printf (_("Watchpoint %d deleted.\n"),
- b->number);
- }
- watchpoint_del_at_next_stop (b);
- e = WP_DELETED;
- }
- switch (e)
- {
- case WP_DELETED:
- /* We've already printed what needs to be printed. */
- bs->print_it = print_it_done;
- /* Stop. */
- break;
- case WP_IGNORE:
- bs->print_it = print_it_noop;
- bs->stop = 0;
- break;
- case WP_VALUE_CHANGED:
- if (b->type == bp_read_watchpoint)
- {
- /* There are two cases to consider here:
- 1. We're watching the triggered memory for reads.
- In that case, trust the target, and always report
- the watchpoint hit to the user. Even though
- reads don't cause value changes, the value may
- have changed since the last time it was read, and
- since we're not trapping writes, we will not see
- those, and as such we should ignore our notion of
- old value.
- 2. We're watching the triggered memory for both
- reads and writes. There are two ways this may
- happen:
- 2.1. This is a target that can't break on data
- reads only, but can break on accesses (reads or
- writes), such as e.g., x86. We detect this case
- at the time we try to insert read watchpoints.
- 2.2. Otherwise, the target supports read
- watchpoints, but, the user set an access or write
- watchpoint watching the same memory as this read
- watchpoint.
- If we're watching memory writes as well as reads,
- ignore watchpoint hits when we find that the
- value hasn't changed, as reads don't cause
- changes. This still gives false positives when
- the program writes the same value to memory as
- what there was already in memory (we will confuse
- it for a read), but it's much better than
- nothing. */
- int other_write_watchpoint = 0;
- if (bl->watchpoint_type == hw_read)
- {
- for (breakpoint *other_b : all_breakpoints ())
- if (other_b->type == bp_hardware_watchpoint
- || other_b->type == bp_access_watchpoint)
- {
- struct watchpoint *other_w =
- (struct watchpoint *) other_b;
- if (other_w->watchpoint_triggered
- == watch_triggered_yes)
- {
- other_write_watchpoint = 1;
- break;
- }
- }
- }
- if (other_write_watchpoint
- || bl->watchpoint_type == hw_access)
- {
- /* We're watching the same memory for writes,
- and the value changed since the last time we
- updated it, so this trap must be for a write.
- Ignore it. */
- bs->print_it = print_it_noop;
- bs->stop = 0;
- }
- }
- break;
- case WP_VALUE_NOT_CHANGED:
- if (b->type == bp_hardware_watchpoint
- || b->type == bp_watchpoint)
- {
- /* Don't stop: write watchpoints shouldn't fire if
- the value hasn't changed. */
- bs->print_it = print_it_noop;
- bs->stop = 0;
- }
- /* Stop. */
- break;
- default:
- /* Can't happen. */
- break;
- }
- }
- else /* must_check_value == 0 */
- {
- /* This is a case where some watchpoint(s) triggered, but
- not at the address of this watchpoint, or else no
- watchpoint triggered after all. So don't print
- anything for this watchpoint. */
- bs->print_it = print_it_noop;
- bs->stop = 0;
- }
- }
- }
- /* For breakpoints that are currently marked as telling gdb to stop,
- check conditions (condition proper, frame, thread and ignore count)
- of breakpoint referred to by BS. If we should not stop for this
- breakpoint, set BS->stop to 0. */
- static void
- bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
- {
- const struct bp_location *bl;
- struct breakpoint *b;
- /* Assume stop. */
- bool condition_result = true;
- struct expression *cond;
- gdb_assert (bs->stop);
- /* BS is built for existing struct breakpoint. */
- bl = bs->bp_location_at.get ();
- gdb_assert (bl != NULL);
- b = bs->breakpoint_at;
- gdb_assert (b != NULL);
- /* Even if the target evaluated the condition on its end and notified GDB, we
- need to do so again since GDB does not know if we stopped due to a
- breakpoint or a single step breakpoint. */
- if (frame_id_p (b->frame_id)
- && !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ())))
- {
- bs->stop = 0;
- return;
- }
- /* If this is a thread/task-specific breakpoint, don't waste cpu
- evaluating the condition if this isn't the specified
- thread/task. */
- if ((b->thread != -1 && b->thread != thread->global_num)
- || (b->task != 0 && b->task != ada_get_task_number (thread)))
- {
- bs->stop = 0;
- return;
- }
- /* Evaluate extension language breakpoints that have a "stop" method
- implemented. */
- bs->stop = breakpoint_ext_lang_cond_says_stop (b);
- if (is_watchpoint (b))
- {
- struct watchpoint *w = (struct watchpoint *) b;
- cond = w->cond_exp.get ();
- }
- else
- cond = bl->cond.get ();
- if (cond && b->disposition != disp_del_at_next_stop)
- {
- int within_current_scope = 1;
- struct watchpoint * w;
- /* We use value_mark and value_free_to_mark because it could
- be a long time before we return to the command level and
- call free_all_values. We can't call free_all_values
- because we might be in the middle of evaluating a
- function call. */
- struct value *mark = value_mark ();
- if (is_watchpoint (b))
- w = (struct watchpoint *) b;
- else
- w = NULL;
- /* Need to select the frame, with all that implies so that
- the conditions will have the right context. Because we
- use the frame, we will not see an inlined function's
- variables when we arrive at a breakpoint at the start
- of the inlined function; the current frame will be the
- call site. */
- if (w == NULL || w->cond_exp_valid_block == NULL)
- select_frame (get_current_frame ());
- else
- {
- struct frame_info *frame;
- /* For local watchpoint expressions, which particular
- instance of a local is being watched matters, so we
- keep track of the frame to evaluate the expression
- in. To evaluate the condition however, it doesn't
- really matter which instantiation of the function
- where the condition makes sense triggers the
- watchpoint. This allows an expression like "watch
- global if q > 10" set in `func', catch writes to
- global on all threads that call `func', or catch
- writes on all recursive calls of `func' by a single
- thread. We simply always evaluate the condition in
- the innermost frame that's executing where it makes
- sense to evaluate the condition. It seems
- intuitive. */
- frame = block_innermost_frame (w->cond_exp_valid_block);
- if (frame != NULL)
- select_frame (frame);
- else
- within_current_scope = 0;
- }
- if (within_current_scope)
- {
- try
- {
- condition_result = breakpoint_cond_eval (cond);
- }
- catch (const gdb_exception &ex)
- {
- exception_fprintf (gdb_stderr, ex,
- "Error in testing breakpoint condition:\n");
- }
- }
- else
- {
- warning (_("Watchpoint condition cannot be tested "
- "in the current scope"));
- /* If we failed to set the right context for this
- watchpoint, unconditionally report it. */
- }
- /* FIXME-someday, should give breakpoint #. */
- value_free_to_mark (mark);
- }
- if (cond && !condition_result)
- {
- bs->stop = 0;
- }
- else if (b->ignore_count > 0)
- {
- b->ignore_count--;
- bs->stop = 0;
- /* Increase the hit count even though we don't stop. */
- ++(b->hit_count);
- gdb::observers::breakpoint_modified.notify (b);
- }
- }
- /* Returns true if we need to track moribund locations of LOC's type
- on the current target. */
- static int
- need_moribund_for_location_type (struct bp_location *loc)
- {
- return ((loc->loc_type == bp_loc_software_breakpoint
- && !target_supports_stopped_by_sw_breakpoint ())
- || (loc->loc_type == bp_loc_hardware_breakpoint
- && !target_supports_stopped_by_hw_breakpoint ()));
- }
- /* See breakpoint.h. */
- bpstat *
- build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr,
- const target_waitstatus &ws)
- {
- bpstat *bs_head = nullptr, **bs_link = &bs_head;
- for (breakpoint *b : all_breakpoints ())
- {
- if (!breakpoint_enabled (b))
- continue;
- for (bp_location *bl : b->locations ())
- {
- /* For hardware watchpoints, we look only at the first
- location. The watchpoint_check function will work on the
- entire expression, not the individual locations. For
- read watchpoints, the watchpoints_triggered function has
- checked all locations already. */
- if (b->type == bp_hardware_watchpoint && bl != b->loc)
- break;
- if (!bl->enabled || bl->disabled_by_cond || bl->shlib_disabled)
- continue;
- if (!bpstat_check_location (bl, aspace, bp_addr, ws))
- continue;
- /* Come here if it's a watchpoint, or if the break address
- matches. */
- bpstat *bs = new bpstat (bl, &bs_link); /* Alloc a bpstat to
- explain stop. */
- /* Assume we stop. Should we find a watchpoint that is not
- actually triggered, or if the condition of the breakpoint
- evaluates as false, we'll reset 'stop' to 0. */
- bs->stop = 1;
- bs->print = 1;
- /* If this is a scope breakpoint, mark the associated
- watchpoint as triggered so that we will handle the
- out-of-scope event. We'll get to the watchpoint next
- iteration. */
- if (b->type == bp_watchpoint_scope && b->related_breakpoint != b)
- {
- struct watchpoint *w = (struct watchpoint *) b->related_breakpoint;
- w->watchpoint_triggered = watch_triggered_yes;
- }
- }
- }
- /* Check if a moribund breakpoint explains the stop. */
- if (!target_supports_stopped_by_sw_breakpoint ()
- || !target_supports_stopped_by_hw_breakpoint ())
- {
- for (bp_location *loc : moribund_locations)
- {
- if (breakpoint_location_address_match (loc, aspace, bp_addr)
- && need_moribund_for_location_type (loc))
- {
- bpstat *bs = new bpstat (loc, &bs_link);
- /* For hits of moribund locations, we should just proceed. */
- bs->stop = 0;
- bs->print = 0;
- bs->print_it = print_it_noop;
- }
- }
- }
- return bs_head;
- }
- /* See breakpoint.h. */
- bpstat *
- bpstat_stop_status (const address_space *aspace,
- CORE_ADDR bp_addr, thread_info *thread,
- const target_waitstatus &ws,
- bpstat *stop_chain)
- {
- struct breakpoint *b = NULL;
- /* First item of allocated bpstat's. */
- bpstat *bs_head = stop_chain;
- bpstat *bs;
- int need_remove_insert;
- int removed_any;
- /* First, build the bpstat chain with locations that explain a
- target stop, while being careful to not set the target running,
- as that may invalidate locations (in particular watchpoint
- locations are recreated). Resuming will happen here with
- breakpoint conditions or watchpoint expressions that include
- inferior function calls. */
- if (bs_head == NULL)
- bs_head = build_bpstat_chain (aspace, bp_addr, ws);
- /* A bit of special processing for shlib breakpoints. We need to
- process solib loading here, so that the lists of loaded and
- unloaded libraries are correct before we handle "catch load" and
- "catch unload". */
- for (bs = bs_head; bs != NULL; bs = bs->next)
- {
- if (bs->breakpoint_at && bs->breakpoint_at->type == bp_shlib_event)
- {
- handle_solib_event ();
- break;
- }
- }
- /* Now go through the locations that caused the target to stop, and
- check whether we're interested in reporting this stop to higher
- layers, or whether we should resume the target transparently. */
- removed_any = 0;
- for (bs = bs_head; bs != NULL; bs = bs->next)
- {
- if (!bs->stop)
- continue;
- b = bs->breakpoint_at;
- b->ops->check_status (bs);
- if (bs->stop)
- {
- bpstat_check_breakpoint_conditions (bs, thread);
- if (bs->stop)
- {
- ++(b->hit_count);
- /* We will stop here. */
- if (b->disposition == disp_disable)
- {
- --(b->enable_count);
- if (b->enable_count <= 0)
- b->enable_state = bp_disabled;
- removed_any = 1;
- }
- gdb::observers::breakpoint_modified.notify (b);
- if (b->silent)
- bs->print = 0;
- bs->commands = b->commands;
- if (command_line_is_silent (bs->commands
- ? bs->commands.get () : NULL))
- bs->print = 0;
- b->ops->after_condition_true (bs);
- }
- }
- /* Print nothing for this entry if we don't stop or don't
- print. */
- if (!bs->stop || !bs->print)
- bs->print_it = print_it_noop;
- }
- /* If we aren't stopping, the value of some hardware watchpoint may
- not have changed, but the intermediate memory locations we are
- watching may have. Don't bother if we're stopping; this will get
- done later. */
- need_remove_insert = 0;
- if (! bpstat_causes_stop (bs_head))
- for (bs = bs_head; bs != NULL; bs = bs->next)
- if (!bs->stop
- && bs->breakpoint_at
- && is_hardware_watchpoint (bs->breakpoint_at))
- {
- struct watchpoint *w = (struct watchpoint *) bs->breakpoint_at;
- update_watchpoint (w, 0 /* don't reparse. */);
- need_remove_insert = 1;
- }
- if (need_remove_insert)
- update_global_location_list (UGLL_MAY_INSERT);
- else if (removed_any)
- update_global_location_list (UGLL_DONT_INSERT);
- return bs_head;
- }
- /* See breakpoint.h. */
- bpstat *
- bpstat_stop_status_nowatch (const address_space *aspace, CORE_ADDR bp_addr,
- thread_info *thread, const target_waitstatus &ws)
- {
- gdb_assert (!target_stopped_by_watchpoint ());
- /* Clear all watchpoints' 'watchpoint_triggered' value from a
- previous stop to avoid confusing bpstat_stop_status. */
- watchpoints_triggered (ws);
- return bpstat_stop_status (aspace, bp_addr, thread, ws);
- }
- static void
- handle_jit_event (CORE_ADDR address)
- {
- struct gdbarch *gdbarch;
- infrun_debug_printf ("handling bp_jit_event");
- /* Switch terminal for any messages produced by
- breakpoint_re_set. */
- target_terminal::ours_for_output ();
- gdbarch = get_frame_arch (get_current_frame ());
- /* This event is caused by a breakpoint set in `jit_breakpoint_re_set`,
- thus it is expected that its objectfile can be found through
- minimal symbol lookup. If it doesn't work (and assert fails), it
- most likely means that `jit_breakpoint_re_set` was changes and this
- function needs to be updated too. */
- bound_minimal_symbol jit_bp_sym = lookup_minimal_symbol_by_pc (address);
- gdb_assert (jit_bp_sym.objfile != nullptr);
- jit_event_handler (gdbarch, jit_bp_sym.objfile);
- target_terminal::inferior ();
- }
- /* Prepare WHAT final decision for infrun. */
- /* Decide what infrun needs to do with this bpstat. */
- struct bpstat_what
- bpstat_what (bpstat *bs_head)
- {
- struct bpstat_what retval;
- bpstat *bs;
- retval.main_action = BPSTAT_WHAT_KEEP_CHECKING;
- retval.call_dummy = STOP_NONE;
- retval.is_longjmp = false;
- for (bs = bs_head; bs != NULL; bs = bs->next)
- {
- /* Extract this BS's action. After processing each BS, we check
- if its action overrides all we've seem so far. */
- enum bpstat_what_main_action this_action = BPSTAT_WHAT_KEEP_CHECKING;
- enum bptype bptype;
- if (bs->breakpoint_at == NULL)
- {
- /* I suspect this can happen if it was a momentary
- breakpoint which has since been deleted. */
- bptype = bp_none;
- }
- else
- bptype = bs->breakpoint_at->type;
- switch (bptype)
- {
- case bp_none:
- break;
- case bp_breakpoint:
- case bp_hardware_breakpoint:
- case bp_single_step:
- case bp_until:
- case bp_finish:
- case bp_shlib_event:
- if (bs->stop)
- {
- if (bs->print)
- this_action = BPSTAT_WHAT_STOP_NOISY;
- else
- this_action = BPSTAT_WHAT_STOP_SILENT;
- }
- else
- this_action = BPSTAT_WHAT_SINGLE;
- break;
- case bp_watchpoint:
- case bp_hardware_watchpoint:
- case bp_read_watchpoint:
- case bp_access_watchpoint:
- if (bs->stop)
- {
- if (bs->print)
- this_action = BPSTAT_WHAT_STOP_NOISY;
- else
- this_action = BPSTAT_WHAT_STOP_SILENT;
- }
- else
- {
- /* There was a watchpoint, but we're not stopping.
- This requires no further action. */
- }
- break;
- case bp_longjmp:
- case bp_longjmp_call_dummy:
- case bp_exception:
- if (bs->stop)
- {
- this_action = BPSTAT_WHAT_SET_LONGJMP_RESUME;
- retval.is_longjmp = bptype != bp_exception;
- }
- else
- this_action = BPSTAT_WHAT_SINGLE;
- break;
- case bp_longjmp_resume:
- case bp_exception_resume:
- if (bs->stop)
- {
- this_action = BPSTAT_WHAT_CLEAR_LONGJMP_RESUME;
- retval.is_longjmp = bptype == bp_longjmp_resume;
- }
- else
- this_action = BPSTAT_WHAT_SINGLE;
- break;
- case bp_step_resume:
- if (bs->stop)
- this_action = BPSTAT_WHAT_STEP_RESUME;
- else
- {
- /* It is for the wrong frame. */
- this_action = BPSTAT_WHAT_SINGLE;
- }
- break;
- case bp_hp_step_resume:
- if (bs->stop)
- this_action = BPSTAT_WHAT_HP_STEP_RESUME;
- else
- {
- /* It is for the wrong frame. */
- this_action = BPSTAT_WHAT_SINGLE;
- }
- break;
- case bp_watchpoint_scope:
- case bp_thread_event:
- case bp_overlay_event:
- case bp_longjmp_master:
- case bp_std_terminate_master:
- case bp_exception_master:
- this_action = BPSTAT_WHAT_SINGLE;
- break;
- case bp_catchpoint:
- if (bs->stop)
- {
- if (bs->print)
- this_action = BPSTAT_WHAT_STOP_NOISY;
- else
- this_action = BPSTAT_WHAT_STOP_SILENT;
- }
- else
- {
- /* Some catchpoints are implemented with breakpoints.
- For those, we need to step over the breakpoint. */
- if (bs->bp_location_at->loc_type != bp_loc_other)
- this_action = BPSTAT_WHAT_SINGLE;
- }
- break;
- case bp_jit_event:
- this_action = BPSTAT_WHAT_SINGLE;
- break;
- case bp_call_dummy:
- /* Make sure the action is stop (silent or noisy),
- so infrun.c pops the dummy frame. */
- retval.call_dummy = STOP_STACK_DUMMY;
- this_action = BPSTAT_WHAT_STOP_SILENT;
- break;
- case bp_std_terminate:
- /* Make sure the action is stop (silent or noisy),
- so infrun.c pops the dummy frame. */
- retval.call_dummy = STOP_STD_TERMINATE;
- this_action = BPSTAT_WHAT_STOP_SILENT;
- break;
- case bp_tracepoint:
- case bp_fast_tracepoint:
- case bp_static_tracepoint:
- /* Tracepoint hits should not be reported back to GDB, and
- if one got through somehow, it should have been filtered
- out already. */
- internal_error (__FILE__, __LINE__,
- _("bpstat_what: tracepoint encountered"));
- break;
- case bp_gnu_ifunc_resolver:
- /* Step over it (and insert bp_gnu_ifunc_resolver_return). */
- this_action = BPSTAT_WHAT_SINGLE;
- break;
- case bp_gnu_ifunc_resolver_return:
- /* The breakpoint will be removed, execution will restart from the
- PC of the former breakpoint. */
- this_action = BPSTAT_WHAT_KEEP_CHECKING;
- break;
- case bp_dprintf:
- if (bs->stop)
- this_action = BPSTAT_WHAT_STOP_SILENT;
- else
- this_action = BPSTAT_WHAT_SINGLE;
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("bpstat_what: unhandled bptype %d"), (int) bptype);
- }
- retval.main_action = std::max (retval.main_action, this_action);
- }
- return retval;
- }
- void
- bpstat_run_callbacks (bpstat *bs_head)
- {
- bpstat *bs;
- for (bs = bs_head; bs != NULL; bs = bs->next)
- {
- struct breakpoint *b = bs->breakpoint_at;
- if (b == NULL)
- continue;
- switch (b->type)
- {
- case bp_jit_event:
- handle_jit_event (bs->bp_location_at->address);
- break;
- case bp_gnu_ifunc_resolver:
- gnu_ifunc_resolver_stop (b);
- break;
- case bp_gnu_ifunc_resolver_return:
- gnu_ifunc_resolver_return_stop (b);
- break;
- }
- }
- }
- /* See breakpoint.h. */
- bool
- bpstat_should_step ()
- {
- for (breakpoint *b : all_breakpoints ())
- if (breakpoint_enabled (b) && b->type == bp_watchpoint && b->loc != NULL)
- return true;
- return false;
- }
- /* See breakpoint.h. */
- bool
- bpstat_causes_stop (bpstat *bs)
- {
- for (; bs != NULL; bs = bs->next)
- if (bs->stop)
- return true;
- return false;
- }
- /* Compute a number of spaces suitable to indent the next line
- so it starts at the position corresponding to the table column
- named COL_NAME in the currently active table of UIOUT. */
- static int
- wrap_indent_at_field (struct ui_out *uiout, const char *col_name)
- {
- int i, total_width, width, align;
- const char *text;
- total_width = 0;
- for (i = 1; uiout->query_table_field (i, &width, &align, &text); i++)
- {
- if (strcmp (text, col_name) == 0)
- return total_width;
- total_width += width + 1;
- }
- return 0;
- }
- /* Determine if the locations of this breakpoint will have their conditions
- evaluated by the target, host or a mix of both. Returns the following:
- "host": Host evals condition.
- "host or target": Host or Target evals condition.
- "target": Target evals condition.
- */
- static const char *
- bp_condition_evaluator (struct breakpoint *b)
- {
- char host_evals = 0;
- char target_evals = 0;
- if (!b)
- return NULL;
- if (!is_breakpoint (b))
- return NULL;
- if (gdb_evaluates_breakpoint_condition_p ()
- || !target_supports_evaluation_of_breakpoint_conditions ())
- return condition_evaluation_host;
- for (bp_location *bl : b->locations ())
- {
- if (bl->cond_bytecode)
- target_evals++;
- else
- host_evals++;
- }
- if (host_evals && target_evals)
- return condition_evaluation_both;
- else if (target_evals)
- return condition_evaluation_target;
- else
- return condition_evaluation_host;
- }
- /* Determine the breakpoint location's condition evaluator. This is
- similar to bp_condition_evaluator, but for locations. */
- static const char *
- bp_location_condition_evaluator (struct bp_location *bl)
- {
- if (bl && !is_breakpoint (bl->owner))
- return NULL;
- if (gdb_evaluates_breakpoint_condition_p ()
- || !target_supports_evaluation_of_breakpoint_conditions ())
- return condition_evaluation_host;
- if (bl && bl->cond_bytecode)
- return condition_evaluation_target;
- else
- return condition_evaluation_host;
- }
- /* Print the LOC location out of the list of B->LOC locations. */
- static void
- print_breakpoint_location (struct breakpoint *b,
- struct bp_location *loc)
- {
- struct ui_out *uiout = current_uiout;
- scoped_restore_current_program_space restore_pspace;
- if (loc != NULL && loc->shlib_disabled)
- loc = NULL;
- if (loc != NULL)
- set_current_program_space (loc->pspace);
- if (b->display_canonical)
- uiout->field_string ("what", event_location_to_string (b->location.get ()));
- else if (loc && loc->symtab)
- {
- const struct symbol *sym = loc->symbol;
- if (sym)
- {
- uiout->text ("in ");
- uiout->field_string ("func", sym->print_name (),
- function_name_style.style ());
- uiout->text (" ");
- uiout->wrap_hint (wrap_indent_at_field (uiout, "what"));
- uiout->text ("at ");
- }
- uiout->field_string ("file",
- symtab_to_filename_for_display (loc->symtab),
- file_name_style.style ());
- uiout->text (":");
- if (uiout->is_mi_like_p ())
- uiout->field_string ("fullname", symtab_to_fullname (loc->symtab));
-
- uiout->field_signed ("line", loc->line_number);
- }
- else if (loc)
- {
- string_file stb;
- print_address_symbolic (loc->gdbarch, loc->address, &stb,
- demangle, "");
- uiout->field_stream ("at", stb);
- }
- else
- {
- uiout->field_string ("pending",
- event_location_to_string (b->location.get ()));
- /* If extra_string is available, it could be holding a condition
- or dprintf arguments. In either case, make sure it is printed,
- too, but only for non-MI streams. */
- if (!uiout->is_mi_like_p () && b->extra_string != NULL)
- {
- if (b->type == bp_dprintf)
- uiout->text (",");
- else
- uiout->text (" ");
- uiout->text (b->extra_string.get ());
- }
- }
- if (loc && is_breakpoint (b)
- && breakpoint_condition_evaluation_mode () == condition_evaluation_target
- && bp_condition_evaluator (b) == condition_evaluation_both)
- {
- uiout->text (" (");
- uiout->field_string ("evaluated-by",
- bp_location_condition_evaluator (loc));
- uiout->text (")");
- }
- }
- static const char *
- bptype_string (enum bptype type)
- {
- struct ep_type_description
- {
- enum bptype type;
- const char *description;
- };
- static struct ep_type_description bptypes[] =
- {
- {bp_none, "?deleted?"},
- {bp_breakpoint, "breakpoint"},
- {bp_hardware_breakpoint, "hw breakpoint"},
- {bp_single_step, "sw single-step"},
- {bp_until, "until"},
- {bp_finish, "finish"},
- {bp_watchpoint, "watchpoint"},
- {bp_hardware_watchpoint, "hw watchpoint"},
- {bp_read_watchpoint, "read watchpoint"},
- {bp_access_watchpoint, "acc watchpoint"},
- {bp_longjmp, "longjmp"},
- {bp_longjmp_resume, "longjmp resume"},
- {bp_longjmp_call_dummy, "longjmp for call dummy"},
- {bp_exception, "exception"},
- {bp_exception_resume, "exception resume"},
- {bp_step_resume, "step resume"},
- {bp_hp_step_resume, "high-priority step resume"},
- {bp_watchpoint_scope, "watchpoint scope"},
- {bp_call_dummy, "call dummy"},
- {bp_std_terminate, "std::terminate"},
- {bp_shlib_event, "shlib events"},
- {bp_thread_event, "thread events"},
- {bp_overlay_event, "overlay events"},
- {bp_longjmp_master, "longjmp master"},
- {bp_std_terminate_master, "std::terminate master"},
- {bp_exception_master, "exception master"},
- {bp_catchpoint, "catchpoint"},
- {bp_tracepoint, "tracepoint"},
- {bp_fast_tracepoint, "fast tracepoint"},
- {bp_static_tracepoint, "static tracepoint"},
- {bp_dprintf, "dprintf"},
- {bp_jit_event, "jit events"},
- {bp_gnu_ifunc_resolver, "STT_GNU_IFUNC resolver"},
- {bp_gnu_ifunc_resolver_return, "STT_GNU_IFUNC resolver return"},
- };
- if (((int) type >= (sizeof (bptypes) / sizeof (bptypes[0])))
- || ((int) type != bptypes[(int) type].type))
- internal_error (__FILE__, __LINE__,
- _("bptypes table does not describe type #%d."),
- (int) type);
- return bptypes[(int) type].description;
- }
- /* For MI, output a field named 'thread-groups' with a list as the value.
- For CLI, prefix the list with the string 'inf'. */
- static void
- output_thread_groups (struct ui_out *uiout,
- const char *field_name,
- const std::vector<int> &inf_nums,
- int mi_only)
- {
- int is_mi = uiout->is_mi_like_p ();
- /* For backward compatibility, don't display inferiors in CLI unless
- there are several. Always display them for MI. */
- if (!is_mi && mi_only)
- return;
- ui_out_emit_list list_emitter (uiout, field_name);
- for (size_t i = 0; i < inf_nums.size (); i++)
- {
- if (is_mi)
- {
- char mi_group[10];
- xsnprintf (mi_group, sizeof (mi_group), "i%d", inf_nums[i]);
- uiout->field_string (NULL, mi_group);
- }
- else
- {
- if (i == 0)
- uiout->text (" inf ");
- else
- uiout->text (", ");
-
- uiout->text (plongest (inf_nums[i]));
- }
- }
- }
- /* Print B to gdb_stdout. If RAW_LOC, print raw breakpoint locations
- instead of going via breakpoint_ops::print_one. This makes "maint
- info breakpoints" show the software breakpoint locations of
- catchpoints, which are considered internal implementation
- detail. */
- static void
- print_one_breakpoint_location (struct breakpoint *b,
- struct bp_location *loc,
- int loc_number,
- struct bp_location **last_loc,
- int allflag, bool raw_loc)
- {
- struct command_line *l;
- static char bpenables[] = "nynny";
- struct ui_out *uiout = current_uiout;
- int header_of_multiple = 0;
- int part_of_multiple = (loc != NULL);
- struct value_print_options opts;
- get_user_print_options (&opts);
- gdb_assert (!loc || loc_number != 0);
- /* See comment in print_one_breakpoint concerning treatment of
- breakpoints with single disabled location. */
- if (loc == NULL
- && (b->loc != NULL
- && (b->loc->next != NULL
- || !b->loc->enabled || b->loc->disabled_by_cond)))
- header_of_multiple = 1;
- if (loc == NULL)
- loc = b->loc;
- annotate_record ();
- /* 1 */
- annotate_field (0);
- if (part_of_multiple)
- uiout->field_fmt ("number", "%d.%d", b->number, loc_number);
- else
- uiout->field_signed ("number", b->number);
- /* 2 */
- annotate_field (1);
- if (part_of_multiple)
- uiout->field_skip ("type");
- else
- uiout->field_string ("type", bptype_string (b->type));
- /* 3 */
- annotate_field (2);
- if (part_of_multiple)
- uiout->field_skip ("disp");
- else
- uiout->field_string ("disp", bpdisp_text (b->disposition));
- /* 4 */
- annotate_field (3);
- /* For locations that are disabled because of an invalid condition,
- display "N*" on CLI, where "*" refers to a footnote below the
- table. For MI, simply display a "N" without a footnote. */
- const char *N = (uiout->is_mi_like_p ()) ? "N" : "N*";
- if (part_of_multiple)
- uiout->field_string ("enabled", (loc->disabled_by_cond ? N
- : (loc->enabled ? "y" : "n")));
- else
- uiout->field_fmt ("enabled", "%c", bpenables[(int) b->enable_state]);
- /* 5 and 6 */
- if (!raw_loc && b->ops != NULL && b->ops->print_one != NULL)
- b->ops->print_one (b, last_loc);
- else
- {
- if (is_watchpoint (b))
- {
- struct watchpoint *w = (struct watchpoint *) b;
- /* Field 4, the address, is omitted (which makes the columns
- not line up too nicely with the headers, but the effect
- is relatively readable). */
- if (opts.addressprint)
- uiout->field_skip ("addr");
- annotate_field (5);
- uiout->field_string ("what", w->exp_string.get ());
- }
- else if (!is_catchpoint (b) || is_exception_catchpoint (b)
- || is_ada_exception_catchpoint (b))
- {
- if (opts.addressprint)
- {
- annotate_field (4);
- if (header_of_multiple)
- uiout->field_string ("addr", "<MULTIPLE>",
- metadata_style.style ());
- else if (b->loc == NULL || loc->shlib_disabled)
- uiout->field_string ("addr", "<PENDING>",
- metadata_style.style ());
- else
- uiout->field_core_addr ("addr",
- loc->gdbarch, loc->address);
- }
- annotate_field (5);
- if (!header_of_multiple)
- print_breakpoint_location (b, loc);
- if (b->loc)
- *last_loc = b->loc;
- }
- }
- if (loc != NULL && !header_of_multiple)
- {
- std::vector<int> inf_nums;
- int mi_only = 1;
- for (inferior *inf : all_inferiors ())
- {
- if (inf->pspace == loc->pspace)
- inf_nums.push_back (inf->num);
- }
- /* For backward compatibility, don't display inferiors in CLI unless
- there are several. Always display for MI. */
- if (allflag
- || (!gdbarch_has_global_breakpoints (target_gdbarch ())
- && (program_spaces.size () > 1
- || number_of_inferiors () > 1)
- /* LOC is for existing B, it cannot be in
- moribund_locations and thus having NULL OWNER. */
- && loc->owner->type != bp_catchpoint))
- mi_only = 0;
- output_thread_groups (uiout, "thread-groups", inf_nums, mi_only);
- }
- if (!part_of_multiple)
- {
- if (b->thread != -1)
- {
- /* FIXME: This seems to be redundant and lost here; see the
- "stop only in" line a little further down. */
- uiout->text (" thread ");
- uiout->field_signed ("thread", b->thread);
- }
- else if (b->task != 0)
- {
- uiout->text (" task ");
- uiout->field_signed ("task", b->task);
- }
- }
- uiout->text ("\n");
- if (!part_of_multiple)
- b->ops->print_one_detail (b, uiout);
- if (part_of_multiple && frame_id_p (b->frame_id))
- {
- annotate_field (6);
- uiout->text ("\tstop only in stack frame at ");
- /* FIXME: cagney/2002-12-01: Shouldn't be poking around inside
- the frame ID. */
- uiout->field_core_addr ("frame",
- b->gdbarch, b->frame_id.stack_addr);
- uiout->text ("\n");
- }
-
- if (!part_of_multiple && b->cond_string)
- {
- annotate_field (7);
- if (is_tracepoint (b))
- uiout->text ("\ttrace only if ");
- else
- uiout->text ("\tstop only if ");
- uiout->field_string ("cond", b->cond_string.get ());
- /* Print whether the target is doing the breakpoint's condition
- evaluation. If GDB is doing the evaluation, don't print anything. */
- if (is_breakpoint (b)
- && breakpoint_condition_evaluation_mode ()
- == condition_evaluation_target)
- {
- uiout->message (" (%pF evals)",
- string_field ("evaluated-by",
- bp_condition_evaluator (b)));
- }
- uiout->text ("\n");
- }
- if (!part_of_multiple && b->thread != -1)
- {
- /* FIXME should make an annotation for this. */
- uiout->text ("\tstop only in thread ");
- if (uiout->is_mi_like_p ())
- uiout->field_signed ("thread", b->thread);
- else
- {
- struct thread_info *thr = find_thread_global_id (b->thread);
- uiout->field_string ("thread", print_thread_id (thr));
- }
- uiout->text ("\n");
- }
-
- if (!part_of_multiple)
- {
- if (b->hit_count)
- {
- /* FIXME should make an annotation for this. */
- if (is_catchpoint (b))
- uiout->text ("\tcatchpoint");
- else if (is_tracepoint (b))
- uiout->text ("\ttracepoint");
- else
- uiout->text ("\tbreakpoint");
- uiout->text (" already hit ");
- uiout->field_signed ("times", b->hit_count);
- if (b->hit_count == 1)
- uiout->text (" time\n");
- else
- uiout->text (" times\n");
- }
- else
- {
- /* Output the count also if it is zero, but only if this is mi. */
- if (uiout->is_mi_like_p ())
- uiout->field_signed ("times", b->hit_count);
- }
- }
- if (!part_of_multiple && b->ignore_count)
- {
- annotate_field (8);
- uiout->message ("\tignore next %pF hits\n",
- signed_field ("ignore", b->ignore_count));
- }
- /* Note that an enable count of 1 corresponds to "enable once"
- behavior, which is reported by the combination of enablement and
- disposition, so we don't need to mention it here. */
- if (!part_of_multiple && b->enable_count > 1)
- {
- annotate_field (8);
- uiout->text ("\tdisable after ");
- /* Tweak the wording to clarify that ignore and enable counts
- are distinct, and have additive effect. */
- if (b->ignore_count)
- uiout->text ("additional ");
- else
- uiout->text ("next ");
- uiout->field_signed ("enable", b->enable_count);
- uiout->text (" hits\n");
- }
- if (!part_of_multiple && is_tracepoint (b))
- {
- struct tracepoint *tp = (struct tracepoint *) b;
- if (tp->traceframe_usage)
- {
- uiout->text ("\ttrace buffer usage ");
- uiout->field_signed ("traceframe-usage", tp->traceframe_usage);
- uiout->text (" bytes\n");
- }
- }
- l = b->commands ? b->commands.get () : NULL;
- if (!part_of_multiple && l)
- {
- annotate_field (9);
- ui_out_emit_tuple tuple_emitter (uiout, "script");
- print_command_lines (uiout, l, 4);
- }
- if (is_tracepoint (b))
- {
- struct tracepoint *t = (struct tracepoint *) b;
- if (!part_of_multiple && t->pass_count)
- {
- annotate_field (10);
- uiout->text ("\tpass count ");
- uiout->field_signed ("pass", t->pass_count);
- uiout->text (" \n");
- }
- /* Don't display it when tracepoint or tracepoint location is
- pending. */
- if (!header_of_multiple && loc != NULL && !loc->shlib_disabled)
- {
- annotate_field (11);
- if (uiout->is_mi_like_p ())
- uiout->field_string ("installed",
- loc->inserted ? "y" : "n");
- else
- {
- if (loc->inserted)
- uiout->text ("\t");
- else
- uiout->text ("\tnot ");
- uiout->text ("installed on target\n");
- }
- }
- }
- if (uiout->is_mi_like_p () && !part_of_multiple)
- {
- if (is_watchpoint (b))
- {
- struct watchpoint *w = (struct watchpoint *) b;
- uiout->field_string ("original-location", w->exp_string.get ());
- }
- else if (b->location != NULL
- && event_location_to_string (b->location.get ()) != NULL)
- uiout->field_string ("original-location",
- event_location_to_string (b->location.get ()));
- }
- }
- /* See breakpoint.h. */
- bool fix_multi_location_breakpoint_output_globally = false;
- static void
- print_one_breakpoint (struct breakpoint *b,
- struct bp_location **last_loc,
- int allflag)
- {
- struct ui_out *uiout = current_uiout;
- bool use_fixed_output
- = (uiout->test_flags (fix_multi_location_breakpoint_output)
- || fix_multi_location_breakpoint_output_globally);
- gdb::optional<ui_out_emit_tuple> bkpt_tuple_emitter (gdb::in_place, uiout, "bkpt");
- print_one_breakpoint_location (b, NULL, 0, last_loc, allflag, false);
- /* The mi2 broken format: the main breakpoint tuple ends here, the locations
- are outside. */
- if (!use_fixed_output)
- bkpt_tuple_emitter.reset ();
- /* If this breakpoint has custom print function,
- it's already printed. Otherwise, print individual
- locations, if any. */
- if (b->ops == NULL
- || b->ops->print_one == NULL
- || allflag)
- {
- /* If breakpoint has a single location that is disabled, we
- print it as if it had several locations, since otherwise it's
- hard to represent "breakpoint enabled, location disabled"
- situation.
- Note that while hardware watchpoints have several locations
- internally, that's not a property exposed to users.
- Likewise, while catchpoints may be implemented with
- breakpoints (e.g., catch throw), that's not a property
- exposed to users. We do however display the internal
- breakpoint locations with "maint info breakpoints". */
- if (!is_hardware_watchpoint (b)
- && (!is_catchpoint (b) || is_exception_catchpoint (b)
- || is_ada_exception_catchpoint (b))
- && (allflag
- || (b->loc && (b->loc->next
- || !b->loc->enabled
- || b->loc->disabled_by_cond))))
- {
- gdb::optional<ui_out_emit_list> locations_list;
- /* For MI version <= 2, keep the behavior where GDB outputs an invalid
- MI record. For later versions, place breakpoint locations in a
- list. */
- if (uiout->is_mi_like_p () && use_fixed_output)
- locations_list.emplace (uiout, "locations");
- int n = 1;
- for (bp_location *loc : b->locations ())
- {
- ui_out_emit_tuple loc_tuple_emitter (uiout, NULL);
- print_one_breakpoint_location (b, loc, n, last_loc,
- allflag, allflag);
- n++;
- }
- }
- }
- }
- static int
- breakpoint_address_bits (struct breakpoint *b)
- {
- int print_address_bits = 0;
- /* Software watchpoints that aren't watching memory don't have an
- address to print. */
- if (is_no_memory_software_watchpoint (b))
- return 0;
- for (bp_location *loc : b->locations ())
- {
- int addr_bit;
- addr_bit = gdbarch_addr_bit (loc->gdbarch);
- if (addr_bit > print_address_bits)
- print_address_bits = addr_bit;
- }
- return print_address_bits;
- }
- /* See breakpoint.h. */
- void
- print_breakpoint (breakpoint *b)
- {
- struct bp_location *dummy_loc = NULL;
- print_one_breakpoint (b, &dummy_loc, 0);
- }
- /* Return true if this breakpoint was set by the user, false if it is
- internal or momentary. */
- int
- user_breakpoint_p (struct breakpoint *b)
- {
- return b->number > 0;
- }
- /* See breakpoint.h. */
- int
- pending_breakpoint_p (struct breakpoint *b)
- {
- return b->loc == NULL;
- }
- /* Print information on breakpoints (including watchpoints and tracepoints).
- If non-NULL, BP_NUM_LIST is a list of numbers and number ranges as
- understood by number_or_range_parser. Only breakpoints included in this
- list are then printed.
- If SHOW_INTERNAL is true, print internal breakpoints.
- If FILTER is non-NULL, call it on each breakpoint and only include the
- ones for which it returns true.
- Return the total number of breakpoints listed. */
- static int
- breakpoint_1 (const char *bp_num_list, bool show_internal,
- bool (*filter) (const struct breakpoint *))
- {
- struct bp_location *last_loc = NULL;
- int nr_printable_breakpoints;
- struct value_print_options opts;
- int print_address_bits = 0;
- int print_type_col_width = 14;
- struct ui_out *uiout = current_uiout;
- bool has_disabled_by_cond_location = false;
- get_user_print_options (&opts);
- /* Compute the number of rows in the table, as well as the size
- required for address fields. */
- nr_printable_breakpoints = 0;
- for (breakpoint *b : all_breakpoints ())
- {
- /* If we have a filter, only list the breakpoints it accepts. */
- if (filter && !filter (b))
- continue;
- /* If we have a BP_NUM_LIST string, it is a list of breakpoints to
- accept. Skip the others. */
- if (bp_num_list != NULL && *bp_num_list != '\0')
- {
- if (show_internal && parse_and_eval_long (bp_num_list) != b->number)
- continue;
- if (!show_internal && !number_is_in_list (bp_num_list, b->number))
- continue;
- }
- if (show_internal || user_breakpoint_p (b))
- {
- int addr_bit, type_len;
- addr_bit = breakpoint_address_bits (b);
- if (addr_bit > print_address_bits)
- print_address_bits = addr_bit;
- type_len = strlen (bptype_string (b->type));
- if (type_len > print_type_col_width)
- print_type_col_width = type_len;
- nr_printable_breakpoints++;
- }
- }
- {
- ui_out_emit_table table_emitter (uiout,
- opts.addressprint ? 6 : 5,
- nr_printable_breakpoints,
- "BreakpointTable");
- if (nr_printable_breakpoints > 0)
- annotate_breakpoints_headers ();
- if (nr_printable_breakpoints > 0)
- annotate_field (0);
- uiout->table_header (7, ui_left, "number", "Num"); /* 1 */
- if (nr_printable_breakpoints > 0)
- annotate_field (1);
- uiout->table_header (print_type_col_width, ui_left, "type", "Type"); /* 2 */
- if (nr_printable_breakpoints > 0)
- annotate_field (2);
- uiout->table_header (4, ui_left, "disp", "Disp"); /* 3 */
- if (nr_printable_breakpoints > 0)
- annotate_field (3);
- uiout->table_header (3, ui_left, "enabled", "Enb"); /* 4 */
- if (opts.addressprint)
- {
- if (nr_printable_breakpoints > 0)
- annotate_field (4);
- if (print_address_bits <= 32)
- uiout->table_header (10, ui_left, "addr", "Address"); /* 5 */
- else
- uiout->table_header (18, ui_left, "addr", "Address"); /* 5 */
- }
- if (nr_printable_breakpoints > 0)
- annotate_field (5);
- uiout->table_header (40, ui_noalign, "what", "What"); /* 6 */
- uiout->table_body ();
- if (nr_printable_breakpoints > 0)
- annotate_breakpoints_table ();
- for (breakpoint *b : all_breakpoints ())
- {
- QUIT;
- /* If we have a filter, only list the breakpoints it accepts. */
- if (filter && !filter (b))
- continue;
- /* If we have a BP_NUM_LIST string, it is a list of breakpoints to
- accept. Skip the others. */
- if (bp_num_list != NULL && *bp_num_list != '\0')
- {
- if (show_internal) /* maintenance info breakpoint */
- {
- if (parse_and_eval_long (bp_num_list) != b->number)
- continue;
- }
- else /* all others */
- {
- if (!number_is_in_list (bp_num_list, b->number))
- continue;
- }
- }
- /* We only print out user settable breakpoints unless the
- show_internal is set. */
- if (show_internal || user_breakpoint_p (b))
- {
- print_one_breakpoint (b, &last_loc, show_internal);
- for (bp_location *loc : b->locations ())
- if (loc->disabled_by_cond)
- has_disabled_by_cond_location = true;
- }
- }
- }
- if (nr_printable_breakpoints == 0)
- {
- /* If there's a filter, let the caller decide how to report
- empty list. */
- if (!filter)
- {
- if (bp_num_list == NULL || *bp_num_list == '\0')
- uiout->message ("No breakpoints or watchpoints.\n");
- else
- uiout->message ("No breakpoint or watchpoint matching '%s'.\n",
- bp_num_list);
- }
- }
- else
- {
- if (last_loc && !server_command)
- set_next_address (last_loc->gdbarch, last_loc->address);
- if (has_disabled_by_cond_location && !uiout->is_mi_like_p ())
- uiout->message (_("(*): Breakpoint condition is invalid at this "
- "location.\n"));
- }
- /* FIXME? Should this be moved up so that it is only called when
- there have been breakpoints? */
- annotate_breakpoints_table_end ();
- return nr_printable_breakpoints;
- }
- /* Display the value of default-collect in a way that is generally
- compatible with the breakpoint list. */
- static void
- default_collect_info (void)
- {
- struct ui_out *uiout = current_uiout;
- /* If it has no value (which is frequently the case), say nothing; a
- message like "No default-collect." gets in user's face when it's
- not wanted. */
- if (default_collect.empty ())
- return;
- /* The following phrase lines up nicely with per-tracepoint collect
- actions. */
- uiout->text ("default collect ");
- uiout->field_string ("default-collect", default_collect);
- uiout->text (" \n");
- }
-
- static void
- info_breakpoints_command (const char *args, int from_tty)
- {
- breakpoint_1 (args, false, NULL);
- default_collect_info ();
- }
- static void
- info_watchpoints_command (const char *args, int from_tty)
- {
- int num_printed = breakpoint_1 (args, false, is_watchpoint);
- struct ui_out *uiout = current_uiout;
- if (num_printed == 0)
- {
- if (args == NULL || *args == '\0')
- uiout->message ("No watchpoints.\n");
- else
- uiout->message ("No watchpoint matching '%s'.\n", args);
- }
- }
- static void
- maintenance_info_breakpoints (const char *args, int from_tty)
- {
- breakpoint_1 (args, true, NULL);
- default_collect_info ();
- }
- static int
- breakpoint_has_pc (struct breakpoint *b,
- struct program_space *pspace,
- CORE_ADDR pc, struct obj_section *section)
- {
- for (bp_location *bl : b->locations ())
- {
- if (bl->pspace == pspace
- && bl->address == pc
- && (!overlay_debugging || bl->section == section))
- return 1;
- }
- return 0;
- }
- /* Print a message describing any user-breakpoints set at PC. This
- concerns with logical breakpoints, so we match program spaces, not
- address spaces. */
- static void
- describe_other_breakpoints (struct gdbarch *gdbarch,
- struct program_space *pspace, CORE_ADDR pc,
- struct obj_section *section, int thread)
- {
- int others = 0;
- for (breakpoint *b : all_breakpoints ())
- others += (user_breakpoint_p (b)
- && breakpoint_has_pc (b, pspace, pc, section));
- if (others > 0)
- {
- if (others == 1)
- gdb_printf (_("Note: breakpoint "));
- else /* if (others == ???) */
- gdb_printf (_("Note: breakpoints "));
- for (breakpoint *b : all_breakpoints ())
- if (user_breakpoint_p (b) && breakpoint_has_pc (b, pspace, pc, section))
- {
- others--;
- gdb_printf ("%d", b->number);
- if (b->thread == -1 && thread != -1)
- gdb_printf (" (all threads)");
- else if (b->thread != -1)
- gdb_printf (" (thread %d)", b->thread);
- gdb_printf ("%s%s ",
- ((b->enable_state == bp_disabled
- || b->enable_state == bp_call_disabled)
- ? " (disabled)"
- : ""),
- (others > 1) ? ","
- : ((others == 1) ? " and" : ""));
- }
- current_uiout->message (_("also set at pc %ps.\n"),
- styled_string (address_style.style (),
- paddress (gdbarch, pc)));
- }
- }
- /* Return true iff it is meaningful to use the address member of LOC.
- For some breakpoint types, the locations' address members are
- irrelevant and it makes no sense to attempt to compare them to
- other addresses (or use them for any other purpose either).
- More specifically, software watchpoints and catchpoints that are
- not backed by breakpoints always have a zero valued location
- address and we don't want to mark breakpoints of any of these types
- to be a duplicate of an actual breakpoint location at address
- zero. */
- static bool
- bl_address_is_meaningful (bp_location *loc)
- {
- return loc->loc_type != bp_loc_other;
- }
- /* Assuming LOC1 and LOC2's owners are hardware watchpoints, returns
- true if LOC1 and LOC2 represent the same watchpoint location. */
- static int
- watchpoint_locations_match (struct bp_location *loc1,
- struct bp_location *loc2)
- {
- struct watchpoint *w1 = (struct watchpoint *) loc1->owner;
- struct watchpoint *w2 = (struct watchpoint *) loc2->owner;
- /* Both of them must exist. */
- gdb_assert (w1 != NULL);
- gdb_assert (w2 != NULL);
- /* If the target can evaluate the condition expression in hardware,
- then we we need to insert both watchpoints even if they are at
- the same place. Otherwise the watchpoint will only trigger when
- the condition of whichever watchpoint was inserted evaluates to
- true, not giving a chance for GDB to check the condition of the
- other watchpoint. */
- if ((w1->cond_exp
- && target_can_accel_watchpoint_condition (loc1->address,
- loc1->length,
- loc1->watchpoint_type,
- w1->cond_exp.get ()))
- || (w2->cond_exp
- && target_can_accel_watchpoint_condition (loc2->address,
- loc2->length,
- loc2->watchpoint_type,
- w2->cond_exp.get ())))
- return 0;
- /* Note that this checks the owner's type, not the location's. In
- case the target does not support read watchpoints, but does
- support access watchpoints, we'll have bp_read_watchpoint
- watchpoints with hw_access locations. Those should be considered
- duplicates of hw_read locations. The hw_read locations will
- become hw_access locations later. */
- return (loc1->owner->type == loc2->owner->type
- && loc1->pspace->aspace == loc2->pspace->aspace
- && loc1->address == loc2->address
- && loc1->length == loc2->length);
- }
- /* See breakpoint.h. */
- int
- breakpoint_address_match (const address_space *aspace1, CORE_ADDR addr1,
- const address_space *aspace2, CORE_ADDR addr2)
- {
- return ((gdbarch_has_global_breakpoints (target_gdbarch ())
- || aspace1 == aspace2)
- && addr1 == addr2);
- }
- /* Returns true if {ASPACE2,ADDR2} falls within the range determined by
- {ASPACE1,ADDR1,LEN1}. In most targets, this can only be true if ASPACE1
- matches ASPACE2. On targets that have global breakpoints, the address
- space doesn't really matter. */
- static int
- breakpoint_address_match_range (const address_space *aspace1,
- CORE_ADDR addr1,
- int len1, const address_space *aspace2,
- CORE_ADDR addr2)
- {
- return ((gdbarch_has_global_breakpoints (target_gdbarch ())
- || aspace1 == aspace2)
- && addr2 >= addr1 && addr2 < addr1 + len1);
- }
- /* Returns true if {ASPACE,ADDR} matches the breakpoint BL. BL may be
- a ranged breakpoint. In most targets, a match happens only if ASPACE
- matches the breakpoint's address space. On targets that have global
- breakpoints, the address space doesn't really matter. */
- static int
- breakpoint_location_address_match (struct bp_location *bl,
- const address_space *aspace,
- CORE_ADDR addr)
- {
- return (breakpoint_address_match (bl->pspace->aspace, bl->address,
- aspace, addr)
- || (bl->length
- && breakpoint_address_match_range (bl->pspace->aspace,
- bl->address, bl->length,
- aspace, addr)));
- }
- /* Returns true if the [ADDR,ADDR+LEN) range in ASPACE overlaps
- breakpoint BL. BL may be a ranged breakpoint. In most targets, a
- match happens only if ASPACE matches the breakpoint's address
- space. On targets that have global breakpoints, the address space
- doesn't really matter. */
- static int
- breakpoint_location_address_range_overlap (struct bp_location *bl,
- const address_space *aspace,
- CORE_ADDR addr, int len)
- {
- if (gdbarch_has_global_breakpoints (target_gdbarch ())
- || bl->pspace->aspace == aspace)
- {
- int bl_len = bl->length != 0 ? bl->length : 1;
- if (mem_ranges_overlap (addr, len, bl->address, bl_len))
- return 1;
- }
- return 0;
- }
- /* If LOC1 and LOC2's owners are not tracepoints, returns false directly.
- Then, if LOC1 and LOC2 represent the same tracepoint location, returns
- true, otherwise returns false. */
- static int
- tracepoint_locations_match (struct bp_location *loc1,
- struct bp_location *loc2)
- {
- if (is_tracepoint (loc1->owner) && is_tracepoint (loc2->owner))
- /* Since tracepoint locations are never duplicated with others', tracepoint
- locations at the same address of different tracepoints are regarded as
- different locations. */
- return (loc1->address == loc2->address && loc1->owner == loc2->owner);
- else
- return 0;
- }
- /* Assuming LOC1 and LOC2's types' have meaningful target addresses
- (bl_address_is_meaningful), returns true if LOC1 and LOC2 represent
- the same location. If SW_HW_BPS_MATCH is true, then software
- breakpoint locations and hardware breakpoint locations match,
- otherwise they don't. */
- static int
- breakpoint_locations_match (struct bp_location *loc1,
- struct bp_location *loc2,
- bool sw_hw_bps_match)
- {
- int hw_point1, hw_point2;
- /* Both of them must not be in moribund_locations. */
- gdb_assert (loc1->owner != NULL);
- gdb_assert (loc2->owner != NULL);
- hw_point1 = is_hardware_watchpoint (loc1->owner);
- hw_point2 = is_hardware_watchpoint (loc2->owner);
- if (hw_point1 != hw_point2)
- return 0;
- else if (hw_point1)
- return watchpoint_locations_match (loc1, loc2);
- else if (is_tracepoint (loc1->owner) || is_tracepoint (loc2->owner))
- return tracepoint_locations_match (loc1, loc2);
- else
- /* We compare bp_location.length in order to cover ranged
- breakpoints. Keep this in sync with
- bp_location_is_less_than. */
- return (breakpoint_address_match (loc1->pspace->aspace, loc1->address,
- loc2->pspace->aspace, loc2->address)
- && (loc1->loc_type == loc2->loc_type || sw_hw_bps_match)
- && loc1->length == loc2->length);
- }
- static void
- breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr,
- int bnum, int have_bnum)
- {
- /* The longest string possibly returned by hex_string_custom
- is 50 chars. These must be at least that big for safety. */
- char astr1[64];
- char astr2[64];
- strcpy (astr1, hex_string_custom ((unsigned long) from_addr, 8));
- strcpy (astr2, hex_string_custom ((unsigned long) to_addr, 8));
- if (have_bnum)
- warning (_("Breakpoint %d address previously adjusted from %s to %s."),
- bnum, astr1, astr2);
- else
- warning (_("Breakpoint address adjusted from %s to %s."), astr1, astr2);
- }
- /* Adjust a breakpoint's address to account for architectural
- constraints on breakpoint placement. Return the adjusted address.
- Note: Very few targets require this kind of adjustment. For most
- targets, this function is simply the identity function. */
- static CORE_ADDR
- adjust_breakpoint_address (struct gdbarch *gdbarch,
- CORE_ADDR bpaddr, enum bptype bptype)
- {
- if (bptype == bp_watchpoint
- || bptype == bp_hardware_watchpoint
- || bptype == bp_read_watchpoint
- || bptype == bp_access_watchpoint
- || bptype == bp_catchpoint)
- {
- /* Watchpoints and the various bp_catch_* eventpoints should not
- have their addresses modified. */
- return bpaddr;
- }
- else if (bptype == bp_single_step)
- {
- /* Single-step breakpoints should not have their addresses
- modified. If there's any architectural constrain that
- applies to this address, then it should have already been
- taken into account when the breakpoint was created in the
- first place. If we didn't do this, stepping through e.g.,
- Thumb-2 IT blocks would break. */
- return bpaddr;
- }
- else
- {
- CORE_ADDR adjusted_bpaddr = bpaddr;
- if (gdbarch_adjust_breakpoint_address_p (gdbarch))
- {
- /* Some targets have architectural constraints on the placement
- of breakpoint instructions. Obtain the adjusted address. */
- adjusted_bpaddr = gdbarch_adjust_breakpoint_address (gdbarch, bpaddr);
- }
- adjusted_bpaddr = address_significant (gdbarch, adjusted_bpaddr);
- /* An adjusted breakpoint address can significantly alter
- a user's expectations. Print a warning if an adjustment
- is required. */
- if (adjusted_bpaddr != bpaddr)
- breakpoint_adjustment_warning (bpaddr, adjusted_bpaddr, 0, 0);
- return adjusted_bpaddr;
- }
- }
- static bp_loc_type
- bp_location_from_bp_type (bptype type)
- {
- switch (type)
- {
- case bp_breakpoint:
- case bp_single_step:
- case bp_until:
- case bp_finish:
- case bp_longjmp:
- case bp_longjmp_resume:
- case bp_longjmp_call_dummy:
- case bp_exception:
- case bp_exception_resume:
- case bp_step_resume:
- case bp_hp_step_resume:
- case bp_watchpoint_scope:
- case bp_call_dummy:
- case bp_std_terminate:
- case bp_shlib_event:
- case bp_thread_event:
- case bp_overlay_event:
- case bp_jit_event:
- case bp_longjmp_master:
- case bp_std_terminate_master:
- case bp_exception_master:
- case bp_gnu_ifunc_resolver:
- case bp_gnu_ifunc_resolver_return:
- case bp_dprintf:
- return bp_loc_software_breakpoint;
- case bp_hardware_breakpoint:
- return bp_loc_hardware_breakpoint;
- case bp_hardware_watchpoint:
- case bp_read_watchpoint:
- case bp_access_watchpoint:
- return bp_loc_hardware_watchpoint;
- case bp_watchpoint:
- case bp_catchpoint:
- case bp_tracepoint:
- case bp_fast_tracepoint:
- case bp_static_tracepoint:
- return bp_loc_other;
- default:
- internal_error (__FILE__, __LINE__, _("unknown breakpoint type"));
- }
- }
- bp_location::bp_location (breakpoint *owner, bp_loc_type type)
- {
- this->owner = owner;
- this->cond_bytecode = NULL;
- this->shlib_disabled = 0;
- this->enabled = 1;
- this->disabled_by_cond = false;
- this->loc_type = type;
- if (this->loc_type == bp_loc_software_breakpoint
- || this->loc_type == bp_loc_hardware_breakpoint)
- mark_breakpoint_location_modified (this);
- incref ();
- }
- bp_location::bp_location (breakpoint *owner)
- : bp_location::bp_location (owner,
- bp_location_from_bp_type (owner->type))
- {
- }
- /* Allocate a struct bp_location. */
- static struct bp_location *
- allocate_bp_location (struct breakpoint *bpt)
- {
- return bpt->ops->allocate_location (bpt);
- }
- /* Decrement reference count. If the reference count reaches 0,
- destroy the bp_location. Sets *BLP to NULL. */
- static void
- decref_bp_location (struct bp_location **blp)
- {
- bp_location_ref_policy::decref (*blp);
- *blp = NULL;
- }
- /* Add breakpoint B at the end of the global breakpoint chain. */
- static breakpoint *
- add_to_breakpoint_chain (std::unique_ptr<breakpoint> &&b)
- {
- struct breakpoint *b1;
- struct breakpoint *result = b.get ();
- /* Add this breakpoint to the end of the chain so that a list of
- breakpoints will come out in order of increasing numbers. */
- b1 = breakpoint_chain;
- if (b1 == 0)
- breakpoint_chain = b.release ();
- else
- {
- while (b1->next)
- b1 = b1->next;
- b1->next = b.release ();
- }
- return result;
- }
- /* Initializes breakpoint B with type BPTYPE and no locations yet. */
- static void
- init_raw_breakpoint_without_location (struct breakpoint *b,
- struct gdbarch *gdbarch,
- enum bptype bptype,
- const struct breakpoint_ops *ops)
- {
- gdb_assert (ops != NULL);
- b->ops = ops;
- b->type = bptype;
- b->gdbarch = gdbarch;
- b->language = current_language->la_language;
- b->input_radix = input_radix;
- b->related_breakpoint = b;
- }
- /* Helper to set_raw_breakpoint below. Creates a breakpoint
- that has type BPTYPE and has no locations as yet. */
- static struct breakpoint *
- set_raw_breakpoint_without_location (struct gdbarch *gdbarch,
- enum bptype bptype,
- const struct breakpoint_ops *ops)
- {
- std::unique_ptr<breakpoint> b = new_breakpoint_from_type (bptype);
- init_raw_breakpoint_without_location (b.get (), gdbarch, bptype, ops);
- return add_to_breakpoint_chain (std::move (b));
- }
- /* Initialize loc->function_name. */
- static void
- set_breakpoint_location_function (struct bp_location *loc)
- {
- gdb_assert (loc->owner != NULL);
- if (loc->owner->type == bp_breakpoint
- || loc->owner->type == bp_hardware_breakpoint
- || is_tracepoint (loc->owner))
- {
- const char *function_name;
- if (loc->msymbol != NULL
- && (MSYMBOL_TYPE (loc->msymbol) == mst_text_gnu_ifunc
- || MSYMBOL_TYPE (loc->msymbol) == mst_data_gnu_ifunc))
- {
- struct breakpoint *b = loc->owner;
- function_name = loc->msymbol->linkage_name ();
- if (b->type == bp_breakpoint && b->loc == loc
- && loc->next == NULL && b->related_breakpoint == b)
- {
- /* Create only the whole new breakpoint of this type but do not
- mess more complicated breakpoints with multiple locations. */
- b->type = bp_gnu_ifunc_resolver;
- /* Remember the resolver's address for use by the return
- breakpoint. */
- loc->related_address = loc->address;
- }
- }
- else
- find_pc_partial_function (loc->address, &function_name, NULL, NULL);
- if (function_name)
- loc->function_name = make_unique_xstrdup (function_name);
- }
- }
- /* Attempt to determine architecture of location identified by SAL. */
- struct gdbarch *
- get_sal_arch (struct symtab_and_line sal)
- {
- if (sal.section)
- return sal.section->objfile->arch ();
- if (sal.symtab)
- return sal.symtab->compunit ()->objfile ()->arch ();
- return NULL;
- }
- /* Low level routine for partially initializing a breakpoint of type
- BPTYPE. The newly created breakpoint's address, section, source
- file name, and line number are provided by SAL.
- It is expected that the caller will complete the initialization of
- the newly created breakpoint struct as well as output any status
- information regarding the creation of a new breakpoint. */
- static void
- init_raw_breakpoint (struct breakpoint *b, struct gdbarch *gdbarch,
- struct symtab_and_line sal, enum bptype bptype,
- const struct breakpoint_ops *ops)
- {
- init_raw_breakpoint_without_location (b, gdbarch, bptype, ops);
- add_location_to_breakpoint (b, &sal);
- if (bptype != bp_catchpoint)
- gdb_assert (sal.pspace != NULL);
- /* Store the program space that was used to set the breakpoint,
- except for ordinary breakpoints, which are independent of the
- program space. */
- if (bptype != bp_breakpoint && bptype != bp_hardware_breakpoint)
- b->pspace = sal.pspace;
- }
- /* set_raw_breakpoint is a low level routine for allocating and
- partially initializing a breakpoint of type BPTYPE. The newly
- created breakpoint's address, section, source file name, and line
- number are provided by SAL. The newly created and partially
- initialized breakpoint is added to the breakpoint chain and
- is also returned as the value of this function.
- It is expected that the caller will complete the initialization of
- the newly created breakpoint struct as well as output any status
- information regarding the creation of a new breakpoint. In
- particular, set_raw_breakpoint does NOT set the breakpoint
- number! Care should be taken to not allow an error to occur
- prior to completing the initialization of the breakpoint. If this
- should happen, a bogus breakpoint will be left on the chain. */
- static struct breakpoint *
- set_raw_breakpoint (struct gdbarch *gdbarch,
- struct symtab_and_line sal, enum bptype bptype,
- const struct breakpoint_ops *ops)
- {
- std::unique_ptr<breakpoint> b = new_breakpoint_from_type (bptype);
- init_raw_breakpoint (b.get (), gdbarch, sal, bptype, ops);
- return add_to_breakpoint_chain (std::move (b));
- }
- /* Call this routine when stepping and nexting to enable a breakpoint
- if we do a longjmp() or 'throw' in TP. FRAME is the frame which
- initiated the operation. */
- void
- set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame)
- {
- int thread = tp->global_num;
- /* To avoid having to rescan all objfile symbols at every step,
- we maintain a list of continually-inserted but always disabled
- longjmp "master" breakpoints. Here, we simply create momentary
- clones of those and enable them for the requested thread. */
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->pspace == current_program_space
- && (b->type == bp_longjmp_master
- || b->type == bp_exception_master))
- {
- enum bptype type = b->type == bp_longjmp_master ? bp_longjmp : bp_exception;
- struct breakpoint *clone;
- /* longjmp_breakpoint_ops ensures INITIATING_FRAME is cleared again
- after their removal. */
- clone = momentary_breakpoint_from_master (b, type,
- &momentary_breakpoint_ops, 1);
- clone->thread = thread;
- }
- tp->initiating_frame = frame;
- }
- /* Delete all longjmp breakpoints from THREAD. */
- void
- delete_longjmp_breakpoint (int thread)
- {
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_longjmp || b->type == bp_exception)
- {
- if (b->thread == thread)
- delete_breakpoint (b);
- }
- }
- void
- delete_longjmp_breakpoint_at_next_stop (int thread)
- {
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_longjmp || b->type == bp_exception)
- {
- if (b->thread == thread)
- b->disposition = disp_del_at_next_stop;
- }
- }
- /* Place breakpoints of type bp_longjmp_call_dummy to catch longjmp for
- INFERIOR_PTID thread. Chain them all by RELATED_BREAKPOINT and return
- pointer to any of them. Return NULL if this system cannot place longjmp
- breakpoints. */
- struct breakpoint *
- set_longjmp_breakpoint_for_call_dummy (void)
- {
- breakpoint *retval = nullptr;
- for (breakpoint *b : all_breakpoints ())
- if (b->pspace == current_program_space && b->type == bp_longjmp_master)
- {
- struct breakpoint *new_b;
- new_b = momentary_breakpoint_from_master (b, bp_longjmp_call_dummy,
- &momentary_breakpoint_ops,
- 1);
- new_b->thread = inferior_thread ()->global_num;
- /* Link NEW_B into the chain of RETVAL breakpoints. */
- gdb_assert (new_b->related_breakpoint == new_b);
- if (retval == NULL)
- retval = new_b;
- new_b->related_breakpoint = retval;
- while (retval->related_breakpoint != new_b->related_breakpoint)
- retval = retval->related_breakpoint;
- retval->related_breakpoint = new_b;
- }
- return retval;
- }
- /* Verify all existing dummy frames and their associated breakpoints for
- TP. Remove those which can no longer be found in the current frame
- stack.
- If the unwind fails then there is not sufficient information to discard
- dummy frames. In this case, elide the clean up and the dummy frames will
- be cleaned up next time this function is called from a location where
- unwinding is possible. */
- void
- check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
- {
- struct breakpoint *b, *b_tmp;
- ALL_BREAKPOINTS_SAFE (b, b_tmp)
- if (b->type == bp_longjmp_call_dummy && b->thread == tp->global_num)
- {
- struct breakpoint *dummy_b = b->related_breakpoint;
- /* Find the bp_call_dummy breakpoint in the list of breakpoints
- chained off b->related_breakpoint. */
- while (dummy_b != b && dummy_b->type != bp_call_dummy)
- dummy_b = dummy_b->related_breakpoint;
- /* If there was no bp_call_dummy breakpoint then there's nothing
- more to do. Or, if the dummy frame associated with the
- bp_call_dummy is still on the stack then we need to leave this
- bp_call_dummy in place. */
- if (dummy_b->type != bp_call_dummy
- || frame_find_by_id (dummy_b->frame_id) != NULL)
- continue;
- /* We didn't find the dummy frame on the stack, this could be
- because we have longjmp'd to a stack frame that is previous to
- the dummy frame, or it could be because the stack unwind is
- broken at some point between the longjmp frame and the dummy
- frame.
- Next we figure out why the stack unwind stopped. If it looks
- like the unwind is complete then we assume the dummy frame has
- been jumped over, however, if the unwind stopped for an
- unexpected reason then we assume the stack unwind is currently
- broken, and that we will (eventually) return to the dummy
- frame.
- It might be tempting to consider using frame_id_inner here, but
- that is not safe. There is no guarantee that the stack frames
- we are looking at here are even on the same stack as the
- original dummy frame, hence frame_id_inner can't be used. See
- the comments on frame_id_inner for more details. */
- bool unwind_finished_unexpectedly = false;
- for (struct frame_info *fi = get_current_frame (); fi != nullptr; )
- {
- struct frame_info *prev = get_prev_frame (fi);
- if (prev == nullptr)
- {
- /* FI is the last stack frame. Why did this frame not
- unwind further? */
- auto stop_reason = get_frame_unwind_stop_reason (fi);
- if (stop_reason != UNWIND_NO_REASON
- && stop_reason != UNWIND_OUTERMOST)
- unwind_finished_unexpectedly = true;
- }
- fi = prev;
- }
- if (unwind_finished_unexpectedly)
- continue;
- dummy_frame_discard (dummy_b->frame_id, tp);
- while (b->related_breakpoint != b)
- {
- if (b_tmp == b->related_breakpoint)
- b_tmp = b->related_breakpoint->next;
- delete_breakpoint (b->related_breakpoint);
- }
- delete_breakpoint (b);
- }
- }
- void
- enable_overlay_breakpoints (void)
- {
- for (breakpoint *b : all_breakpoints ())
- if (b->type == bp_overlay_event)
- {
- b->enable_state = bp_enabled;
- update_global_location_list (UGLL_MAY_INSERT);
- overlay_events_enabled = 1;
- }
- }
- void
- disable_overlay_breakpoints (void)
- {
- for (breakpoint *b : all_breakpoints ())
- if (b->type == bp_overlay_event)
- {
- b->enable_state = bp_disabled;
- update_global_location_list (UGLL_DONT_INSERT);
- overlay_events_enabled = 0;
- }
- }
- /* Set an active std::terminate breakpoint for each std::terminate
- master breakpoint. */
- void
- set_std_terminate_breakpoint (void)
- {
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->pspace == current_program_space
- && b->type == bp_std_terminate_master)
- {
- momentary_breakpoint_from_master (b, bp_std_terminate,
- &momentary_breakpoint_ops, 1);
- }
- }
- /* Delete all the std::terminate breakpoints. */
- void
- delete_std_terminate_breakpoint (void)
- {
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_std_terminate)
- delete_breakpoint (b);
- }
- struct breakpoint *
- create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
- {
- struct breakpoint *b;
- b = create_internal_breakpoint (gdbarch, address, bp_thread_event,
- &internal_breakpoint_ops);
- b->enable_state = bp_enabled;
- /* location has to be used or breakpoint_re_set will delete me. */
- b->location = new_address_location (b->loc->address, NULL, 0);
- update_global_location_list_nothrow (UGLL_MAY_INSERT);
- return b;
- }
- struct lang_and_radix
- {
- enum language lang;
- int radix;
- };
- /* Create a breakpoint for JIT code registration and unregistration. */
- struct breakpoint *
- create_jit_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
- {
- return create_internal_breakpoint (gdbarch, address, bp_jit_event,
- &internal_breakpoint_ops);
- }
- /* Remove JIT code registration and unregistration breakpoint(s). */
- void
- remove_jit_event_breakpoints (void)
- {
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_jit_event
- && b->loc->pspace == current_program_space)
- delete_breakpoint (b);
- }
- void
- remove_solib_event_breakpoints (void)
- {
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_shlib_event
- && b->loc->pspace == current_program_space)
- delete_breakpoint (b);
- }
- /* See breakpoint.h. */
- void
- remove_solib_event_breakpoints_at_next_stop (void)
- {
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->type == bp_shlib_event
- && b->loc->pspace == current_program_space)
- b->disposition = disp_del_at_next_stop;
- }
- /* Helper for create_solib_event_breakpoint /
- create_and_insert_solib_event_breakpoint. Allows specifying which
- INSERT_MODE to pass through to update_global_location_list. */
- static struct breakpoint *
- create_solib_event_breakpoint_1 (struct gdbarch *gdbarch, CORE_ADDR address,
- enum ugll_insert_mode insert_mode)
- {
- struct breakpoint *b;
- b = create_internal_breakpoint (gdbarch, address, bp_shlib_event,
- &internal_breakpoint_ops);
- update_global_location_list_nothrow (insert_mode);
- return b;
- }
- struct breakpoint *
- create_solib_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
- {
- return create_solib_event_breakpoint_1 (gdbarch, address, UGLL_MAY_INSERT);
- }
- /* See breakpoint.h. */
- struct breakpoint *
- create_and_insert_solib_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
- {
- struct breakpoint *b;
- /* Explicitly tell update_global_location_list to insert
- locations. */
- b = create_solib_event_breakpoint_1 (gdbarch, address, UGLL_INSERT);
- if (!b->loc->inserted)
- {
- delete_breakpoint (b);
- return NULL;
- }
- return b;
- }
- /* Disable any breakpoints that are on code in shared libraries. Only
- apply to enabled breakpoints, disabled ones can just stay disabled. */
- void
- disable_breakpoints_in_shlibs (void)
- {
- for (bp_location *loc : all_bp_locations ())
- {
- /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL. */
- struct breakpoint *b = loc->owner;
- /* We apply the check to all breakpoints, including disabled for
- those with loc->duplicate set. This is so that when breakpoint
- becomes enabled, or the duplicate is removed, gdb will try to
- insert all breakpoints. If we don't set shlib_disabled here,
- we'll try to insert those breakpoints and fail. */
- if (((b->type == bp_breakpoint)
- || (b->type == bp_jit_event)
- || (b->type == bp_hardware_breakpoint)
- || (is_tracepoint (b)))
- && loc->pspace == current_program_space
- && !loc->shlib_disabled
- && solib_name_from_address (loc->pspace, loc->address)
- )
- {
- loc->shlib_disabled = 1;
- }
- }
- }
- /* Disable any breakpoints and tracepoints that are in SOLIB upon
- notification of unloaded_shlib. Only apply to enabled breakpoints,
- disabled ones can just stay disabled. */
- static void
- disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
- {
- int disabled_shlib_breaks = 0;
- for (bp_location *loc : all_bp_locations ())
- {
- /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL. */
- struct breakpoint *b = loc->owner;
- if (solib->pspace == loc->pspace
- && !loc->shlib_disabled
- && (((b->type == bp_breakpoint
- || b->type == bp_jit_event
- || b->type == bp_hardware_breakpoint)
- && (loc->loc_type == bp_loc_hardware_breakpoint
- || loc->loc_type == bp_loc_software_breakpoint))
- || is_tracepoint (b))
- && solib_contains_address_p (solib, loc->address))
- {
- loc->shlib_disabled = 1;
- /* At this point, we cannot rely on remove_breakpoint
- succeeding so we must mark the breakpoint as not inserted
- to prevent future errors occurring in remove_breakpoints. */
- loc->inserted = 0;
- /* This may cause duplicate notifications for the same breakpoint. */
- gdb::observers::breakpoint_modified.notify (b);
- if (!disabled_shlib_breaks)
- {
- target_terminal::ours_for_output ();
- warning (_("Temporarily disabling breakpoints "
- "for unloaded shared library \"%s\""),
- solib->so_name);
- }
- disabled_shlib_breaks = 1;
- }
- }
- }
- /* Disable any breakpoints and tracepoints in OBJFILE upon
- notification of free_objfile. Only apply to enabled breakpoints,
- disabled ones can just stay disabled. */
- static void
- disable_breakpoints_in_freed_objfile (struct objfile *objfile)
- {
- if (objfile == NULL)
- return;
- /* OBJF_SHARED|OBJF_USERLOADED objfiles are dynamic modules manually
- managed by the user with add-symbol-file/remove-symbol-file.
- Similarly to how breakpoints in shared libraries are handled in
- response to "nosharedlibrary", mark breakpoints in such modules
- shlib_disabled so they end up uninserted on the next global
- location list update. Shared libraries not loaded by the user
- aren't handled here -- they're already handled in
- disable_breakpoints_in_unloaded_shlib, called by solib.c's
- solib_unloaded observer. We skip objfiles that are not
- OBJF_SHARED as those aren't considered dynamic objects (e.g. the
- main objfile). */
- if ((objfile->flags & OBJF_SHARED) == 0
- || (objfile->flags & OBJF_USERLOADED) == 0)
- return;
- for (breakpoint *b : all_breakpoints ())
- {
- int bp_modified = 0;
- if (!is_breakpoint (b) && !is_tracepoint (b))
- continue;
- for (bp_location *loc : b->locations ())
- {
- CORE_ADDR loc_addr = loc->address;
- if (loc->loc_type != bp_loc_hardware_breakpoint
- && loc->loc_type != bp_loc_software_breakpoint)
- continue;
- if (loc->shlib_disabled != 0)
- continue;
- if (objfile->pspace != loc->pspace)
- continue;
- if (loc->loc_type != bp_loc_hardware_breakpoint
- && loc->loc_type != bp_loc_software_breakpoint)
- continue;
- if (is_addr_in_objfile (loc_addr, objfile))
- {
- loc->shlib_disabled = 1;
- /* At this point, we don't know whether the object was
- unmapped from the inferior or not, so leave the
- inserted flag alone. We'll handle failure to
- uninsert quietly, in case the object was indeed
- unmapped. */
- mark_breakpoint_location_modified (loc);
- bp_modified = 1;
- }
- }
- if (bp_modified)
- gdb::observers::breakpoint_modified.notify (b);
- }
- }
- /* An instance of this type is used to represent an solib catchpoint.
- A breakpoint is really of this type iff its ops pointer points to
- CATCH_SOLIB_BREAKPOINT_OPS. */
- struct solib_catchpoint : public breakpoint
- {
- /* True for "catch load", false for "catch unload". */
- bool is_load;
- /* Regular expression to match, if any. COMPILED is only valid when
- REGEX is non-NULL. */
- gdb::unique_xmalloc_ptr<char> regex;
- std::unique_ptr<compiled_regex> compiled;
- };
- static int
- insert_catch_solib (struct bp_location *ignore)
- {
- return 0;
- }
- static int
- remove_catch_solib (struct bp_location *ignore, enum remove_bp_reason reason)
- {
- return 0;
- }
- static int
- breakpoint_hit_catch_solib (const struct bp_location *bl,
- const address_space *aspace,
- CORE_ADDR bp_addr,
- const target_waitstatus &ws)
- {
- struct solib_catchpoint *self = (struct solib_catchpoint *) bl->owner;
- if (ws.kind () == TARGET_WAITKIND_LOADED)
- return 1;
- for (breakpoint *other : all_breakpoints ())
- {
- if (other == bl->owner)
- continue;
- if (other->type != bp_shlib_event)
- continue;
- if (self->pspace != NULL && other->pspace != self->pspace)
- continue;
- for (bp_location *other_bl : other->locations ())
- {
- if (other->ops->breakpoint_hit (other_bl, aspace, bp_addr, ws))
- return 1;
- }
- }
- return 0;
- }
- static void
- check_status_catch_solib (struct bpstat *bs)
- {
- struct solib_catchpoint *self
- = (struct solib_catchpoint *) bs->breakpoint_at;
- if (self->is_load)
- {
- for (so_list *iter : current_program_space->added_solibs)
- {
- if (!self->regex
- || self->compiled->exec (iter->so_name, 0, NULL, 0) == 0)
- return;
- }
- }
- else
- {
- for (const std::string &iter : current_program_space->deleted_solibs)
- {
- if (!self->regex
- || self->compiled->exec (iter.c_str (), 0, NULL, 0) == 0)
- return;
- }
- }
- bs->stop = 0;
- bs->print_it = print_it_noop;
- }
- static enum print_stop_action
- print_it_catch_solib (bpstat *bs)
- {
- struct breakpoint *b = bs->breakpoint_at;
- struct ui_out *uiout = current_uiout;
- annotate_catchpoint (b->number);
- maybe_print_thread_hit_breakpoint (uiout);
- if (b->disposition == disp_del)
- uiout->text ("Temporary catchpoint ");
- else
- uiout->text ("Catchpoint ");
- uiout->field_signed ("bkptno", b->number);
- uiout->text ("\n");
- if (uiout->is_mi_like_p ())
- uiout->field_string ("disp", bpdisp_text (b->disposition));
- print_solib_event (1);
- return PRINT_SRC_AND_LOC;
- }
- static void
- print_one_catch_solib (struct breakpoint *b, struct bp_location **locs)
- {
- struct solib_catchpoint *self = (struct solib_catchpoint *) b;
- struct value_print_options opts;
- struct ui_out *uiout = current_uiout;
- get_user_print_options (&opts);
- /* Field 4, the address, is omitted (which makes the columns not
- line up too nicely with the headers, but the effect is relatively
- readable). */
- if (opts.addressprint)
- {
- annotate_field (4);
- uiout->field_skip ("addr");
- }
- std::string msg;
- annotate_field (5);
- if (self->is_load)
- {
- if (self->regex)
- msg = string_printf (_("load of library matching %s"),
- self->regex.get ());
- else
- msg = _("load of library");
- }
- else
- {
- if (self->regex)
- msg = string_printf (_("unload of library matching %s"),
- self->regex.get ());
- else
- msg = _("unload of library");
- }
- uiout->field_string ("what", msg);
- if (uiout->is_mi_like_p ())
- uiout->field_string ("catch-type", self->is_load ? "load" : "unload");
- }
- static void
- print_mention_catch_solib (struct breakpoint *b)
- {
- struct solib_catchpoint *self = (struct solib_catchpoint *) b;
- gdb_printf (_("Catchpoint %d (%s)"), b->number,
- self->is_load ? "load" : "unload");
- }
- static void
- print_recreate_catch_solib (struct breakpoint *b, struct ui_file *fp)
- {
- struct solib_catchpoint *self = (struct solib_catchpoint *) b;
- gdb_printf (fp, "%s %s",
- b->disposition == disp_del ? "tcatch" : "catch",
- self->is_load ? "load" : "unload");
- if (self->regex)
- gdb_printf (fp, " %s", self->regex.get ());
- gdb_printf (fp, "\n");
- }
- static struct breakpoint_ops catch_solib_breakpoint_ops;
- /* See breakpoint.h. */
- void
- add_solib_catchpoint (const char *arg, bool is_load, bool is_temp, bool enabled)
- {
- struct gdbarch *gdbarch = get_current_arch ();
- if (!arg)
- arg = "";
- arg = skip_spaces (arg);
- std::unique_ptr<solib_catchpoint> c (new solib_catchpoint ());
- if (*arg != '\0')
- {
- c->compiled.reset (new compiled_regex (arg, REG_NOSUB,
- _("Invalid regexp")));
- c->regex = make_unique_xstrdup (arg);
- }
- c->is_load = is_load;
- init_catchpoint (c.get (), gdbarch, is_temp, NULL,
- &catch_solib_breakpoint_ops);
- c->enable_state = enabled ? bp_enabled : bp_disabled;
- install_breakpoint (0, std::move (c), 1);
- }
- /* A helper function that does all the work for "catch load" and
- "catch unload". */
- static void
- catch_load_or_unload (const char *arg, int from_tty, int is_load,
- struct cmd_list_element *command)
- {
- const int enabled = 1;
- bool temp = command->context () == CATCH_TEMPORARY;
- add_solib_catchpoint (arg, is_load, temp, enabled);
- }
- static void
- catch_load_command_1 (const char *arg, int from_tty,
- struct cmd_list_element *command)
- {
- catch_load_or_unload (arg, from_tty, 1, command);
- }
- static void
- catch_unload_command_1 (const char *arg, int from_tty,
- struct cmd_list_element *command)
- {
- catch_load_or_unload (arg, from_tty, 0, command);
- }
- /* See breakpoint.h. */
- void
- init_catchpoint (struct breakpoint *b,
- struct gdbarch *gdbarch, bool temp,
- const char *cond_string,
- const struct breakpoint_ops *ops)
- {
- symtab_and_line sal;
- sal.pspace = current_program_space;
- init_raw_breakpoint (b, gdbarch, sal, bp_catchpoint, ops);
- if (cond_string == nullptr)
- b->cond_string.reset ();
- else
- b->cond_string = make_unique_xstrdup (cond_string);
- b->disposition = temp ? disp_del : disp_donttouch;
- }
- void
- install_breakpoint (int internal, std::unique_ptr<breakpoint> &&arg, int update_gll)
- {
- breakpoint *b = add_to_breakpoint_chain (std::move (arg));
- set_breakpoint_number (internal, b);
- if (is_tracepoint (b))
- set_tracepoint_count (breakpoint_count);
- if (!internal)
- mention (b);
- gdb::observers::breakpoint_created.notify (b);
- if (update_gll)
- update_global_location_list (UGLL_MAY_INSERT);
- }
- static int
- hw_breakpoint_used_count (void)
- {
- int i = 0;
- for (breakpoint *b : all_breakpoints ())
- if (b->type == bp_hardware_breakpoint && breakpoint_enabled (b))
- for (bp_location *bl : b->locations ())
- {
- /* Special types of hardware breakpoints may use more than
- one register. */
- i += b->ops->resources_needed (bl);
- }
- return i;
- }
- /* Returns the resources B would use if it were a hardware
- watchpoint. */
- static int
- hw_watchpoint_use_count (struct breakpoint *b)
- {
- int i = 0;
- if (!breakpoint_enabled (b))
- return 0;
- for (bp_location *bl : b->locations ())
- {
- /* Special types of hardware watchpoints may use more than
- one register. */
- i += b->ops->resources_needed (bl);
- }
- return i;
- }
- /* Returns the sum the used resources of all hardware watchpoints of
- type TYPE in the breakpoints list. Also returns in OTHER_TYPE_USED
- the sum of the used resources of all hardware watchpoints of other
- types _not_ TYPE. */
- static int
- hw_watchpoint_used_count_others (struct breakpoint *except,
- enum bptype type, int *other_type_used)
- {
- int i = 0;
- *other_type_used = 0;
- for (breakpoint *b : all_breakpoints ())
- {
- if (b == except)
- continue;
- if (!breakpoint_enabled (b))
- continue;
- if (b->type == type)
- i += hw_watchpoint_use_count (b);
- else if (is_hardware_watchpoint (b))
- *other_type_used = 1;
- }
- return i;
- }
- void
- disable_watchpoints_before_interactive_call_start (void)
- {
- for (breakpoint *b : all_breakpoints ())
- if (is_watchpoint (b) && breakpoint_enabled (b))
- {
- b->enable_state = bp_call_disabled;
- update_global_location_list (UGLL_DONT_INSERT);
- }
- }
- void
- enable_watchpoints_after_interactive_call_stop (void)
- {
- for (breakpoint *b : all_breakpoints ())
- if (is_watchpoint (b) && b->enable_state == bp_call_disabled)
- {
- b->enable_state = bp_enabled;
- update_global_location_list (UGLL_MAY_INSERT);
- }
- }
- void
- disable_breakpoints_before_startup (void)
- {
- current_program_space->executing_startup = 1;
- update_global_location_list (UGLL_DONT_INSERT);
- }
- void
- enable_breakpoints_after_startup (void)
- {
- current_program_space->executing_startup = 0;
- breakpoint_re_set ();
- }
- /* Create a new single-step breakpoint for thread THREAD, with no
- locations. */
- static struct breakpoint *
- new_single_step_breakpoint (int thread, struct gdbarch *gdbarch)
- {
- std::unique_ptr<breakpoint> b (new breakpoint ());
- init_raw_breakpoint_without_location (b.get (), gdbarch, bp_single_step,
- &momentary_breakpoint_ops);
- b->disposition = disp_donttouch;
- b->frame_id = null_frame_id;
- b->thread = thread;
- gdb_assert (b->thread != 0);
- return add_to_breakpoint_chain (std::move (b));
- }
- /* Set a momentary breakpoint of type TYPE at address specified by
- SAL. If FRAME_ID is valid, the breakpoint is restricted to that
- frame. */
- breakpoint_up
- set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal,
- struct frame_id frame_id, enum bptype type)
- {
- struct breakpoint *b;
- /* If FRAME_ID is valid, it should be a real frame, not an inlined or
- tail-called one. */
- gdb_assert (!frame_id_artificial_p (frame_id));
- b = set_raw_breakpoint (gdbarch, sal, type, &momentary_breakpoint_ops);
- b->enable_state = bp_enabled;
- b->disposition = disp_donttouch;
- b->frame_id = frame_id;
- b->thread = inferior_thread ()->global_num;
- update_global_location_list_nothrow (UGLL_MAY_INSERT);
- return breakpoint_up (b);
- }
- /* Make a momentary breakpoint based on the master breakpoint ORIG.
- The new breakpoint will have type TYPE, use OPS as its
- breakpoint_ops, and will set enabled to LOC_ENABLED. */
- static struct breakpoint *
- momentary_breakpoint_from_master (struct breakpoint *orig,
- enum bptype type,
- const struct breakpoint_ops *ops,
- int loc_enabled)
- {
- struct breakpoint *copy;
- copy = set_raw_breakpoint_without_location (orig->gdbarch, type, ops);
- copy->loc = allocate_bp_location (copy);
- set_breakpoint_location_function (copy->loc);
- copy->loc->gdbarch = orig->loc->gdbarch;
- copy->loc->requested_address = orig->loc->requested_address;
- copy->loc->address = orig->loc->address;
- copy->loc->section = orig->loc->section;
- copy->loc->pspace = orig->loc->pspace;
- copy->loc->probe = orig->loc->probe;
- copy->loc->line_number = orig->loc->line_number;
- copy->loc->symtab = orig->loc->symtab;
- copy->loc->enabled = loc_enabled;
- copy->frame_id = orig->frame_id;
- copy->thread = orig->thread;
- copy->pspace = orig->pspace;
- copy->enable_state = bp_enabled;
- copy->disposition = disp_donttouch;
- copy->number = internal_breakpoint_number--;
- update_global_location_list_nothrow (UGLL_DONT_INSERT);
- return copy;
- }
- /* Make a deep copy of momentary breakpoint ORIG. Returns NULL if
- ORIG is NULL. */
- struct breakpoint *
- clone_momentary_breakpoint (struct breakpoint *orig)
- {
- /* If there's nothing to clone, then return nothing. */
- if (orig == NULL)
- return NULL;
- return momentary_breakpoint_from_master (orig, orig->type, orig->ops, 0);
- }
- breakpoint_up
- set_momentary_breakpoint_at_pc (struct gdbarch *gdbarch, CORE_ADDR pc,
- enum bptype type)
- {
- struct symtab_and_line sal;
- sal = find_pc_line (pc, 0);
- sal.pc = pc;
- sal.section = find_pc_overlay (pc);
- sal.explicit_pc = 1;
- return set_momentary_breakpoint (gdbarch, sal, null_frame_id, type);
- }
- /* Tell the user we have just set a breakpoint B. */
- static void
- mention (struct breakpoint *b)
- {
- b->ops->print_mention (b);
- current_uiout->text ("\n");
- }
- static bool bp_loc_is_permanent (struct bp_location *loc);
- /* Handle "set breakpoint auto-hw on".
- If the explicitly specified breakpoint type is not hardware
- breakpoint, check the memory map to see whether the breakpoint
- address is in read-only memory.
- - location type is not hardware breakpoint, memory is read-only.
- We change the type of the location to hardware breakpoint.
- - location type is hardware breakpoint, memory is read-write. This
- means we've previously made the location hardware one, but then the
- memory map changed, so we undo.
- */
- static void
- handle_automatic_hardware_breakpoints (bp_location *bl)
- {
- if (automatic_hardware_breakpoints
- && bl->owner->type != bp_hardware_breakpoint
- && (bl->loc_type == bp_loc_software_breakpoint
- || bl->loc_type == bp_loc_hardware_breakpoint))
- {
- /* When breakpoints are removed, remove_breakpoints will use
- location types we've just set here, the only possible problem
- is that memory map has changed during running program, but
- it's not going to work anyway with current gdb. */
- mem_region *mr = lookup_mem_region (bl->address);
- if (mr != nullptr)
- {
- enum bp_loc_type new_type;
- if (mr->attrib.mode != MEM_RW)
- new_type = bp_loc_hardware_breakpoint;
- else
- new_type = bp_loc_software_breakpoint;
- if (new_type != bl->loc_type)
- {
- static bool said = false;
- bl->loc_type = new_type;
- if (!said)
- {
- gdb_printf (_("Note: automatically using "
- "hardware breakpoints for "
- "read-only addresses.\n"));
- said = true;
- }
- }
- }
- }
- }
- static struct bp_location *
- add_location_to_breakpoint (struct breakpoint *b,
- const struct symtab_and_line *sal)
- {
- struct bp_location *loc, **tmp;
- CORE_ADDR adjusted_address;
- struct gdbarch *loc_gdbarch = get_sal_arch (*sal);
- if (loc_gdbarch == NULL)
- loc_gdbarch = b->gdbarch;
- /* Adjust the breakpoint's address prior to allocating a location.
- Once we call allocate_bp_location(), that mostly uninitialized
- location will be placed on the location chain. Adjustment of the
- breakpoint may cause target_read_memory() to be called and we do
- not want its scan of the location chain to find a breakpoint and
- location that's only been partially initialized. */
- adjusted_address = adjust_breakpoint_address (loc_gdbarch,
- sal->pc, b->type);
- /* Sort the locations by their ADDRESS. */
- loc = allocate_bp_location (b);
- for (tmp = &(b->loc); *tmp != NULL && (*tmp)->address <= adjusted_address;
- tmp = &((*tmp)->next))
- ;
- loc->next = *tmp;
- *tmp = loc;
- loc->requested_address = sal->pc;
- loc->address = adjusted_address;
- loc->pspace = sal->pspace;
- loc->probe.prob = sal->prob;
- loc->probe.objfile = sal->objfile;
- gdb_assert (loc->pspace != NULL);
- loc->section = sal->section;
- loc->gdbarch = loc_gdbarch;
- loc->line_number = sal->line;
- loc->symtab = sal->symtab;
- loc->symbol = sal->symbol;
- loc->msymbol = sal->msymbol;
- loc->objfile = sal->objfile;
- set_breakpoint_location_function (loc);
- /* While by definition, permanent breakpoints are already present in the
- code, we don't mark the location as inserted. Normally one would expect
- that GDB could rely on that breakpoint instruction to stop the program,
- thus removing the need to insert its own breakpoint, except that executing
- the breakpoint instruction can kill the target instead of reporting a
- SIGTRAP. E.g., on SPARC, when interrupts are disabled, executing the
- instruction resets the CPU, so QEMU 2.0.0 for SPARC correspondingly dies
- with "Trap 0x02 while interrupts disabled, Error state". Letting the
- breakpoint be inserted normally results in QEMU knowing about the GDB
- breakpoint, and thus trap before the breakpoint instruction is executed.
- (If GDB later needs to continue execution past the permanent breakpoint,
- it manually increments the PC, thus avoiding executing the breakpoint
- instruction.) */
- if (bp_loc_is_permanent (loc))
- loc->permanent = 1;
- return loc;
- }
- /* Return true if LOC is pointing to a permanent breakpoint,
- return false otherwise. */
- static bool
- bp_loc_is_permanent (struct bp_location *loc)
- {
- gdb_assert (loc != NULL);
- /* If we have a non-breakpoint-backed catchpoint or a software
- watchpoint, just return 0. We should not attempt to read from
- the addresses the locations of these breakpoint types point to.
- gdbarch_program_breakpoint_here_p, below, will attempt to read
- memory. */
- if (!bl_address_is_meaningful (loc))
- return false;
- scoped_restore_current_pspace_and_thread restore_pspace_thread;
- switch_to_program_space_and_thread (loc->pspace);
- return gdbarch_program_breakpoint_here_p (loc->gdbarch, loc->address);
- }
- /* Build a command list for the dprintf corresponding to the current
- settings of the dprintf style options. */
- static void
- update_dprintf_command_list (struct breakpoint *b)
- {
- const char *dprintf_args = b->extra_string.get ();
- gdb::unique_xmalloc_ptr<char> printf_line = nullptr;
- if (!dprintf_args)
- return;
- dprintf_args = skip_spaces (dprintf_args);
- /* Allow a comma, as it may have terminated a location, but don't
- insist on it. */
- if (*dprintf_args == ',')
- ++dprintf_args;
- dprintf_args = skip_spaces (dprintf_args);
- if (*dprintf_args != '"')
- error (_("Bad format string, missing '\"'."));
- if (strcmp (dprintf_style, dprintf_style_gdb) == 0)
- printf_line = xstrprintf ("printf %s", dprintf_args);
- else if (strcmp (dprintf_style, dprintf_style_call) == 0)
- {
- if (dprintf_function.empty ())
- error (_("No function supplied for dprintf call"));
- if (!dprintf_channel.empty ())
- printf_line = xstrprintf ("call (void) %s (%s,%s)",
- dprintf_function.c_str (),
- dprintf_channel.c_str (),
- dprintf_args);
- else
- printf_line = xstrprintf ("call (void) %s (%s)",
- dprintf_function.c_str (),
- dprintf_args);
- }
- else if (strcmp (dprintf_style, dprintf_style_agent) == 0)
- {
- if (target_can_run_breakpoint_commands ())
- printf_line = xstrprintf ("agent-printf %s", dprintf_args);
- else
- {
- warning (_("Target cannot run dprintf commands, falling back to GDB printf"));
- printf_line = xstrprintf ("printf %s", dprintf_args);
- }
- }
- else
- internal_error (__FILE__, __LINE__,
- _("Invalid dprintf style."));
- gdb_assert (printf_line != NULL);
- /* Manufacture a printf sequence. */
- struct command_line *printf_cmd_line
- = new struct command_line (simple_control, printf_line.release ());
- breakpoint_set_commands (b, counted_command_line (printf_cmd_line,
- command_lines_deleter ()));
- }
- /* Update all dprintf commands, making their command lists reflect
- current style settings. */
- static void
- update_dprintf_commands (const char *args, int from_tty,
- struct cmd_list_element *c)
- {
- for (breakpoint *b : all_breakpoints ())
- if (b->type == bp_dprintf)
- update_dprintf_command_list (b);
- }
- /* Create a breakpoint with SAL as location. Use LOCATION
- as a description of the location, and COND_STRING
- as condition expression. If LOCATION is NULL then create an
- "address location" from the address in the SAL. */
- static void
- init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
- gdb::array_view<const symtab_and_line> sals,
- event_location_up &&location,
- gdb::unique_xmalloc_ptr<char> filter,
- gdb::unique_xmalloc_ptr<char> cond_string,
- gdb::unique_xmalloc_ptr<char> extra_string,
- enum bptype type, enum bpdisp disposition,
- int thread, int task, int ignore_count,
- const struct breakpoint_ops *ops, int from_tty,
- int enabled, int internal, unsigned flags,
- int display_canonical)
- {
- int i;
- if (type == bp_hardware_breakpoint)
- {
- int target_resources_ok;
- i = hw_breakpoint_used_count ();
- target_resources_ok =
- target_can_use_hardware_watchpoint (bp_hardware_breakpoint,
- i + 1, 0);
- if (target_resources_ok == 0)
- error (_("No hardware breakpoint support in the target."));
- else if (target_resources_ok < 0)
- error (_("Hardware breakpoints used exceeds limit."));
- }
- gdb_assert (!sals.empty ());
- for (const auto &sal : sals)
- {
- struct bp_location *loc;
- if (from_tty)
- {
- struct gdbarch *loc_gdbarch = get_sal_arch (sal);
- if (!loc_gdbarch)
- loc_gdbarch = gdbarch;
- describe_other_breakpoints (loc_gdbarch,
- sal.pspace, sal.pc, sal.section, thread);
- }
- if (&sal == &sals[0])
- {
- init_raw_breakpoint (b, gdbarch, sal, type, ops);
- b->thread = thread;
- b->task = task;
- b->cond_string = std::move (cond_string);
- b->extra_string = std::move (extra_string);
- b->ignore_count = ignore_count;
- b->enable_state = enabled ? bp_enabled : bp_disabled;
- b->disposition = disposition;
- if ((flags & CREATE_BREAKPOINT_FLAGS_INSERTED) != 0)
- b->loc->inserted = 1;
- if (type == bp_static_tracepoint)
- {
- struct tracepoint *t = (struct tracepoint *) b;
- struct static_tracepoint_marker marker;
- if (strace_marker_p (b))
- {
- /* We already know the marker exists, otherwise, we
- wouldn't see a sal for it. */
- const char *p
- = &event_location_to_string (b->location.get ())[3];
- const char *endp;
- p = skip_spaces (p);
- endp = skip_to_space (p);
- t->static_trace_marker_id.assign (p, endp - p);
- gdb_printf (_("Probed static tracepoint "
- "marker \"%s\"\n"),
- t->static_trace_marker_id.c_str ());
- }
- else if (target_static_tracepoint_marker_at (sal.pc, &marker))
- {
- t->static_trace_marker_id = std::move (marker.str_id);
- gdb_printf (_("Probed static tracepoint "
- "marker \"%s\"\n"),
- t->static_trace_marker_id.c_str ());
- }
- else
- warning (_("Couldn't determine the static "
- "tracepoint marker to probe"));
- }
- loc = b->loc;
- }
- else
- {
- loc = add_location_to_breakpoint (b, &sal);
- if ((flags & CREATE_BREAKPOINT_FLAGS_INSERTED) != 0)
- loc->inserted = 1;
- }
- /* Do not set breakpoint locations conditions yet. As locations
- are inserted, they get sorted based on their addresses. Let
- the list stabilize to have reliable location numbers. */
- /* Dynamic printf requires and uses additional arguments on the
- command line, otherwise it's an error. */
- if (type == bp_dprintf)
- {
- if (b->extra_string)
- update_dprintf_command_list (b);
- else
- error (_("Format string required"));
- }
- else if (b->extra_string)
- error (_("Garbage '%s' at end of command"), b->extra_string.get ());
- }
- /* The order of the locations is now stable. Set the location
- condition using the location's number. */
- int loc_num = 1;
- for (bp_location *loc : b->locations ())
- {
- if (b->cond_string != nullptr)
- set_breakpoint_location_condition (b->cond_string.get (), loc,
- b->number, loc_num);
- ++loc_num;
- }
- b->display_canonical = display_canonical;
- if (location != NULL)
- b->location = std::move (location);
- else
- b->location = new_address_location (b->loc->address, NULL, 0);
- b->filter = std::move (filter);
- }
- static void
- create_breakpoint_sal (struct gdbarch *gdbarch,
- gdb::array_view<const symtab_and_line> sals,
- event_location_up &&location,
- gdb::unique_xmalloc_ptr<char> filter,
- gdb::unique_xmalloc_ptr<char> cond_string,
- gdb::unique_xmalloc_ptr<char> extra_string,
- enum bptype type, enum bpdisp disposition,
- int thread, int task, int ignore_count,
- const struct breakpoint_ops *ops, int from_tty,
- int enabled, int internal, unsigned flags,
- int display_canonical)
- {
- std::unique_ptr<breakpoint> b = new_breakpoint_from_type (type);
- init_breakpoint_sal (b.get (), gdbarch,
- sals, std::move (location),
- std::move (filter),
- std::move (cond_string),
- std::move (extra_string),
- type, disposition,
- thread, task, ignore_count,
- ops, from_tty,
- enabled, internal, flags,
- display_canonical);
- install_breakpoint (internal, std::move (b), 0);
- }
- /* Add SALS.nelts breakpoints to the breakpoint table. For each
- SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i]
- value. COND_STRING, if not NULL, specified the condition to be
- used for all breakpoints. Essentially the only case where
- SALS.nelts is not 1 is when we set a breakpoint on an overloaded
- function. In that case, it's still not possible to specify
- separate conditions for different overloaded functions, so
- we take just a single condition string.
-
- NOTE: If the function succeeds, the caller is expected to cleanup
- the arrays ADDR_STRING, COND_STRING, and SALS (but not the
- array contents). If the function fails (error() is called), the
- caller is expected to cleanups both the ADDR_STRING, COND_STRING,
- COND and SALS arrays and each of those arrays contents. */
- static void
- create_breakpoints_sal (struct gdbarch *gdbarch,
- struct linespec_result *canonical,
- gdb::unique_xmalloc_ptr<char> cond_string,
- gdb::unique_xmalloc_ptr<char> extra_string,
- enum bptype type, enum bpdisp disposition,
- int thread, int task, int ignore_count,
- const struct breakpoint_ops *ops, int from_tty,
- int enabled, int internal, unsigned flags)
- {
- if (canonical->pre_expanded)
- gdb_assert (canonical->lsals.size () == 1);
- for (const auto &lsal : canonical->lsals)
- {
- /* Note that 'location' can be NULL in the case of a plain
- 'break', without arguments. */
- event_location_up location
- = (canonical->location != NULL
- ? copy_event_location (canonical->location.get ()) : NULL);
- gdb::unique_xmalloc_ptr<char> filter_string
- (lsal.canonical != NULL ? xstrdup (lsal.canonical) : NULL);
- create_breakpoint_sal (gdbarch, lsal.sals,
- std::move (location),
- std::move (filter_string),
- std::move (cond_string),
- std::move (extra_string),
- type, disposition,
- thread, task, ignore_count, ops,
- from_tty, enabled, internal, flags,
- canonical->special_display);
- }
- }
- /* Parse LOCATION which is assumed to be a SAL specification possibly
- followed by conditionals. On return, SALS contains an array of SAL
- addresses found. LOCATION points to the end of the SAL (for
- linespec locations).
- The array and the line spec strings are allocated on the heap, it is
- the caller's responsibility to free them. */
- static void
- parse_breakpoint_sals (struct event_location *location,
- struct linespec_result *canonical)
- {
- struct symtab_and_line cursal;
- if (event_location_type (location) == LINESPEC_LOCATION)
- {
- const char *spec = get_linespec_location (location)->spec_string;
- if (spec == NULL)
- {
- /* The last displayed codepoint, if it's valid, is our default
- breakpoint address. */
- if (last_displayed_sal_is_valid ())
- {
- /* Set sal's pspace, pc, symtab, and line to the values
- corresponding to the last call to print_frame_info.
- Be sure to reinitialize LINE with NOTCURRENT == 0
- as the breakpoint line number is inappropriate otherwise.
- find_pc_line would adjust PC, re-set it back. */
- symtab_and_line sal = get_last_displayed_sal ();
- CORE_ADDR pc = sal.pc;
- sal = find_pc_line (pc, 0);
- /* "break" without arguments is equivalent to "break *PC"
- where PC is the last displayed codepoint's address. So
- make sure to set sal.explicit_pc to prevent GDB from
- trying to expand the list of sals to include all other
- instances with the same symtab and line. */
- sal.pc = pc;
- sal.explicit_pc = 1;
- struct linespec_sals lsal;
- lsal.sals = {sal};
- lsal.canonical = NULL;
- canonical->lsals.push_back (std::move (lsal));
- return;
- }
- else
- error (_("No default breakpoint address now."));
- }
- }
- /* Force almost all breakpoints to be in terms of the
- current_source_symtab (which is decode_line_1's default).
- This should produce the results we want almost all of the
- time while leaving default_breakpoint_* alone.
- ObjC: However, don't match an Objective-C method name which
- may have a '+' or '-' succeeded by a '['. */
- cursal = get_current_source_symtab_and_line ();
- if (last_displayed_sal_is_valid ())
- {
- const char *spec = NULL;
- if (event_location_type (location) == LINESPEC_LOCATION)
- spec = get_linespec_location (location)->spec_string;
- if (!cursal.symtab
- || (spec != NULL
- && strchr ("+-", spec[0]) != NULL
- && spec[1] != '['))
- {
- decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, NULL,
- get_last_displayed_symtab (),
- get_last_displayed_line (),
- canonical, NULL, NULL);
- return;
- }
- }
- decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, NULL,
- cursal.symtab, cursal.line, canonical, NULL, NULL);
- }
- /* Convert each SAL into a real PC. Verify that the PC can be
- inserted as a breakpoint. If it can't throw an error. */
- static void
- breakpoint_sals_to_pc (std::vector<symtab_and_line> &sals)
- {
- for (auto &sal : sals)
- resolve_sal_pc (&sal);
- }
- /* Fast tracepoints may have restrictions on valid locations. For
- instance, a fast tracepoint using a jump instead of a trap will
- likely have to overwrite more bytes than a trap would, and so can
- only be placed where the instruction is longer than the jump, or a
- multi-instruction sequence does not have a jump into the middle of
- it, etc. */
- static void
- check_fast_tracepoint_sals (struct gdbarch *gdbarch,
- gdb::array_view<const symtab_and_line> sals)
- {
- for (const auto &sal : sals)
- {
- struct gdbarch *sarch;
- sarch = get_sal_arch (sal);
- /* We fall back to GDBARCH if there is no architecture
- associated with SAL. */
- if (sarch == NULL)
- sarch = gdbarch;
- std::string msg;
- if (!gdbarch_fast_tracepoint_valid_at (sarch, sal.pc, &msg))
- error (_("May not have a fast tracepoint at %s%s"),
- paddress (sarch, sal.pc), msg.c_str ());
- }
- }
- /* Given TOK, a string specification of condition and thread, as
- accepted by the 'break' command, extract the condition
- string and thread number and set *COND_STRING and *THREAD.
- PC identifies the context at which the condition should be parsed.
- If no condition is found, *COND_STRING is set to NULL.
- If no thread is found, *THREAD is set to -1. */
- static void
- find_condition_and_thread (const char *tok, CORE_ADDR pc,
- gdb::unique_xmalloc_ptr<char> *cond_string,
- int *thread, int *task,
- gdb::unique_xmalloc_ptr<char> *rest)
- {
- cond_string->reset ();
- *thread = -1;
- *task = 0;
- rest->reset ();
- bool force = false;
- while (tok && *tok)
- {
- const char *end_tok;
- int toklen;
- const char *cond_start = NULL;
- const char *cond_end = NULL;
- tok = skip_spaces (tok);
- if ((*tok == '"' || *tok == ',') && rest)
- {
- rest->reset (savestring (tok, strlen (tok)));
- return;
- }
- end_tok = skip_to_space (tok);
- toklen = end_tok - tok;
- if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
- {
- tok = cond_start = end_tok + 1;
- try
- {
- parse_exp_1 (&tok, pc, block_for_pc (pc), 0);
- }
- catch (const gdb_exception_error &)
- {
- if (!force)
- throw;
- else
- tok = tok + strlen (tok);
- }
- cond_end = tok;
- cond_string->reset (savestring (cond_start, cond_end - cond_start));
- }
- else if (toklen >= 1 && strncmp (tok, "-force-condition", toklen) == 0)
- {
- tok = tok + toklen;
- force = true;
- }
- else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
- {
- const char *tmptok;
- struct thread_info *thr;
- tok = end_tok + 1;
- thr = parse_thread_id (tok, &tmptok);
- if (tok == tmptok)
- error (_("Junk after thread keyword."));
- *thread = thr->global_num;
- tok = tmptok;
- }
- else if (toklen >= 1 && strncmp (tok, "task", toklen) == 0)
- {
- char *tmptok;
- tok = end_tok + 1;
- *task = strtol (tok, &tmptok, 0);
- if (tok == tmptok)
- error (_("Junk after task keyword."));
- if (!valid_task_id (*task))
- error (_("Unknown task %d."), *task);
- tok = tmptok;
- }
- else if (rest)
- {
- rest->reset (savestring (tok, strlen (tok)));
- return;
- }
- else
- error (_("Junk at end of arguments."));
- }
- }
- /* Call 'find_condition_and_thread' for each sal in SALS until a parse
- succeeds. The parsed values are written to COND_STRING, THREAD,
- TASK, and REST. See the comment of 'find_condition_and_thread'
- for the description of these parameters and INPUT. */
- static void
- find_condition_and_thread_for_sals (const std::vector<symtab_and_line> &sals,
- const char *input,
- gdb::unique_xmalloc_ptr<char> *cond_string,
- int *thread, int *task,
- gdb::unique_xmalloc_ptr<char> *rest)
- {
- int num_failures = 0;
- for (auto &sal : sals)
- {
- gdb::unique_xmalloc_ptr<char> cond;
- int thread_id = 0;
- int task_id = 0;
- gdb::unique_xmalloc_ptr<char> remaining;
- /* Here we want to parse 'arg' to separate condition from thread
- number. But because parsing happens in a context and the
- contexts of sals might be different, try each until there is
- success. Finding one successful parse is sufficient for our
- goal. When setting the breakpoint we'll re-parse the
- condition in the context of each sal. */
- try
- {
- find_condition_and_thread (input, sal.pc, &cond, &thread_id,
- &task_id, &remaining);
- *cond_string = std::move (cond);
- *thread = thread_id;
- *task = task_id;
- *rest = std::move (remaining);
- break;
- }
- catch (const gdb_exception_error &e)
- {
- num_failures++;
- /* If no sal remains, do not continue. */
- if (num_failures == sals.size ())
- throw;
- }
- }
- }
- /* Decode a static tracepoint marker spec. */
- static std::vector<symtab_and_line>
- decode_static_tracepoint_spec (const char **arg_p)
- {
- const char *p = &(*arg_p)[3];
- const char *endp;
- p = skip_spaces (p);
- endp = skip_to_space (p);
- std::string marker_str (p, endp - p);
- std::vector<static_tracepoint_marker> markers
- = target_static_tracepoint_markers_by_strid (marker_str.c_str ());
- if (markers.empty ())
- error (_("No known static tracepoint marker named %s"),
- marker_str.c_str ());
- std::vector<symtab_and_line> sals;
- sals.reserve (markers.size ());
- for (const static_tracepoint_marker &marker : markers)
- {
- symtab_and_line sal = find_pc_line (marker.address, 0);
- sal.pc = marker.address;
- sals.push_back (sal);
- }
- *arg_p = endp;
- return sals;
- }
- /* Returns the breakpoint ops appropriate for use with with LOCATION_TYPE and
- according to IS_TRACEPOINT. */
- static const struct breakpoint_ops *
- breakpoint_ops_for_event_location_type (enum event_location_type location_type,
- bool is_tracepoint)
- {
- if (is_tracepoint)
- {
- if (location_type == PROBE_LOCATION)
- return &tracepoint_probe_breakpoint_ops;
- else
- return &tracepoint_breakpoint_ops;
- }
- else
- {
- if (location_type == PROBE_LOCATION)
- return &bkpt_probe_breakpoint_ops;
- else
- return &bkpt_breakpoint_ops;
- }
- }
- /* See breakpoint.h. */
- const struct breakpoint_ops *
- breakpoint_ops_for_event_location (const struct event_location *location,
- bool is_tracepoint)
- {
- if (location != nullptr)
- return breakpoint_ops_for_event_location_type
- (event_location_type (location), is_tracepoint);
- return is_tracepoint ? &tracepoint_breakpoint_ops : &bkpt_breakpoint_ops;
- }
- /* See breakpoint.h. */
- int
- create_breakpoint (struct gdbarch *gdbarch,
- struct event_location *location,
- const char *cond_string,
- int thread, const char *extra_string,
- bool force_condition, int parse_extra,
- int tempflag, enum bptype type_wanted,
- int ignore_count,
- enum auto_boolean pending_break_support,
- const struct breakpoint_ops *ops,
- int from_tty, int enabled, int internal,
- unsigned flags)
- {
- struct linespec_result canonical;
- int pending = 0;
- int task = 0;
- int prev_bkpt_count = breakpoint_count;
- gdb_assert (ops != NULL);
- /* If extra_string isn't useful, set it to NULL. */
- if (extra_string != NULL && *extra_string == '\0')
- extra_string = NULL;
- try
- {
- ops->create_sals_from_location (location, &canonical, type_wanted);
- }
- catch (const gdb_exception_error &e)
- {
- /* If caller is interested in rc value from parse, set
- value. */
- if (e.error == NOT_FOUND_ERROR)
- {
- /* If pending breakpoint support is turned off, throw
- error. */
- if (pending_break_support == AUTO_BOOLEAN_FALSE)
- throw;
- exception_print (gdb_stderr, e);
- /* If pending breakpoint support is auto query and the user
- selects no, then simply return the error code. */
- if (pending_break_support == AUTO_BOOLEAN_AUTO
- && !nquery (_("Make %s pending on future shared library load? "),
- bptype_string (type_wanted)))
- return 0;
- /* At this point, either the user was queried about setting
- a pending breakpoint and selected yes, or pending
- breakpoint behavior is on and thus a pending breakpoint
- is defaulted on behalf of the user. */
- pending = 1;
- }
- else
- throw;
- }
- if (!pending && canonical.lsals.empty ())
- return 0;
- /* Resolve all line numbers to PC's and verify that the addresses
- are ok for the target. */
- if (!pending)
- {
- for (auto &lsal : canonical.lsals)
- breakpoint_sals_to_pc (lsal.sals);
- }
- /* Fast tracepoints may have additional restrictions on location. */
- if (!pending && type_wanted == bp_fast_tracepoint)
- {
- for (const auto &lsal : canonical.lsals)
- check_fast_tracepoint_sals (gdbarch, lsal.sals);
- }
- /* Verify that condition can be parsed, before setting any
- breakpoints. Allocate a separate condition expression for each
- breakpoint. */
- if (!pending)
- {
- gdb::unique_xmalloc_ptr<char> cond_string_copy;
- gdb::unique_xmalloc_ptr<char> extra_string_copy;
- if (parse_extra)
- {
- gdb::unique_xmalloc_ptr<char> rest;
- gdb::unique_xmalloc_ptr<char> cond;
- const linespec_sals &lsal = canonical.lsals[0];
- find_condition_and_thread_for_sals (lsal.sals, extra_string,
- &cond, &thread, &task, &rest);
- cond_string_copy = std::move (cond);
- extra_string_copy = std::move (rest);
- }
- else
- {
- if (type_wanted != bp_dprintf
- && extra_string != NULL && *extra_string != '\0')
- error (_("Garbage '%s' at end of location"), extra_string);
- /* Check the validity of the condition. We should error out
- if the condition is invalid at all of the locations and
- if it is not forced. In the PARSE_EXTRA case above, this
- check is done when parsing the EXTRA_STRING. */
- if (cond_string != nullptr && !force_condition)
- {
- int num_failures = 0;
- const linespec_sals &lsal = canonical.lsals[0];
- for (const auto &sal : lsal.sals)
- {
- const char *cond = cond_string;
- try
- {
- parse_exp_1 (&cond, sal.pc, block_for_pc (sal.pc), 0);
- /* One success is sufficient to keep going. */
- break;
- }
- catch (const gdb_exception_error &)
- {
- num_failures++;
- /* If this is the last sal, error out. */
- if (num_failures == lsal.sals.size ())
- throw;
- }
- }
- }
- /* Create a private copy of condition string. */
- if (cond_string)
- cond_string_copy.reset (xstrdup (cond_string));
- /* Create a private copy of any extra string. */
- if (extra_string)
- extra_string_copy.reset (xstrdup (extra_string));
- }
- ops->create_breakpoints_sal (gdbarch, &canonical,
- std::move (cond_string_copy),
- std::move (extra_string_copy),
- type_wanted,
- tempflag ? disp_del : disp_donttouch,
- thread, task, ignore_count, ops,
- from_tty, enabled, internal, flags);
- }
- else
- {
- std::unique_ptr <breakpoint> b = new_breakpoint_from_type (type_wanted);
- init_raw_breakpoint_without_location (b.get (), gdbarch, type_wanted, ops);
- b->location = copy_event_location (location);
- if (parse_extra)
- b->cond_string = NULL;
- else
- {
- /* Create a private copy of condition string. */
- b->cond_string.reset (cond_string != NULL
- ? xstrdup (cond_string)
- : NULL);
- b->thread = thread;
- }
- /* Create a private copy of any extra string. */
- b->extra_string.reset (extra_string != NULL
- ? xstrdup (extra_string)
- : NULL);
- b->ignore_count = ignore_count;
- b->disposition = tempflag ? disp_del : disp_donttouch;
- b->condition_not_parsed = 1;
- b->enable_state = enabled ? bp_enabled : bp_disabled;
- if ((type_wanted != bp_breakpoint
- && type_wanted != bp_hardware_breakpoint) || thread != -1)
- b->pspace = current_program_space;
- install_breakpoint (internal, std::move (b), 0);
- }
-
- if (canonical.lsals.size () > 1)
- {
- warning (_("Multiple breakpoints were set.\nUse the "
- "\"delete\" command to delete unwanted breakpoints."));
- prev_breakpoint_count = prev_bkpt_count;
- }
- update_global_location_list (UGLL_MAY_INSERT);
- return 1;
- }
- /* Set a breakpoint.
- ARG is a string describing breakpoint address,
- condition, and thread.
- FLAG specifies if a breakpoint is hardware on,
- and if breakpoint is temporary, using BP_HARDWARE_FLAG
- and BP_TEMPFLAG. */
- static void
- break_command_1 (const char *arg, int flag, int from_tty)
- {
- int tempflag = flag & BP_TEMPFLAG;
- enum bptype type_wanted = (flag & BP_HARDWAREFLAG
- ? bp_hardware_breakpoint
- : bp_breakpoint);
- event_location_up location = string_to_event_location (&arg, current_language);
- const struct breakpoint_ops *ops = breakpoint_ops_for_event_location
- (location.get (), false /* is_tracepoint */);
- create_breakpoint (get_current_arch (),
- location.get (),
- NULL, 0, arg, false, 1 /* parse arg */,
- tempflag, type_wanted,
- 0 /* Ignore count */,
- pending_break_support,
- ops,
- from_tty,
- 1 /* enabled */,
- 0 /* internal */,
- 0);
- }
- /* Helper function for break_command_1 and disassemble_command. */
- void
- resolve_sal_pc (struct symtab_and_line *sal)
- {
- CORE_ADDR pc;
- if (sal->pc == 0 && sal->symtab != NULL)
- {
- if (!find_line_pc (sal->symtab, sal->line, &pc))
- error (_("No line %d in file \"%s\"."),
- sal->line, symtab_to_filename_for_display (sal->symtab));
- sal->pc = pc;
- /* If this SAL corresponds to a breakpoint inserted using a line
- number, then skip the function prologue if necessary. */
- if (sal->explicit_line)
- skip_prologue_sal (sal);
- }
- if (sal->section == 0 && sal->symtab != NULL)
- {
- const struct blockvector *bv;
- const struct block *b;
- struct symbol *sym;
- bv = blockvector_for_pc_sect (sal->pc, 0, &b,
- sal->symtab->compunit ());
- if (bv != NULL)
- {
- sym = block_linkage_function (b);
- if (sym != NULL)
- {
- fixup_symbol_section (sym, sal->symtab->compunit ()->objfile ());
- sal->section
- = sym->obj_section (sal->symtab->compunit ()->objfile ());
- }
- else
- {
- /* It really is worthwhile to have the section, so we'll
- just have to look harder. This case can be executed
- if we have line numbers but no functions (as can
- happen in assembly source). */
- scoped_restore_current_pspace_and_thread restore_pspace_thread;
- switch_to_program_space_and_thread (sal->pspace);
- bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (sal->pc);
- if (msym.minsym)
- sal->section = msym.obj_section ();
- }
- }
- }
- }
- void
- break_command (const char *arg, int from_tty)
- {
- break_command_1 (arg, 0, from_tty);
- }
- void
- tbreak_command (const char *arg, int from_tty)
- {
- break_command_1 (arg, BP_TEMPFLAG, from_tty);
- }
- static void
- hbreak_command (const char *arg, int from_tty)
- {
- break_command_1 (arg, BP_HARDWAREFLAG, from_tty);
- }
- static void
- thbreak_command (const char *arg, int from_tty)
- {
- break_command_1 (arg, (BP_TEMPFLAG | BP_HARDWAREFLAG), from_tty);
- }
- /* The dynamic printf command is mostly like a regular breakpoint, but
- with a prewired command list consisting of a single output command,
- built from extra arguments supplied on the dprintf command
- line. */
- static void
- dprintf_command (const char *arg, int from_tty)
- {
- event_location_up location = string_to_event_location (&arg, current_language);
- /* If non-NULL, ARG should have been advanced past the location;
- the next character must be ','. */
- if (arg != NULL)
- {
- if (arg[0] != ',' || arg[1] == '\0')
- error (_("Format string required"));
- else
- {
- /* Skip the comma. */
- ++arg;
- }
- }
- create_breakpoint (get_current_arch (),
- location.get (),
- NULL, 0, arg, false, 1 /* parse arg */,
- 0, bp_dprintf,
- 0 /* Ignore count */,
- pending_break_support,
- &dprintf_breakpoint_ops,
- from_tty,
- 1 /* enabled */,
- 0 /* internal */,
- 0);
- }
- static void
- agent_printf_command (const char *arg, int from_tty)
- {
- error (_("May only run agent-printf on the target"));
- }
- /* Implement the "breakpoint_hit" breakpoint_ops method for
- ranged breakpoints. */
- static int
- breakpoint_hit_ranged_breakpoint (const struct bp_location *bl,
- const address_space *aspace,
- CORE_ADDR bp_addr,
- const target_waitstatus &ws)
- {
- if (ws.kind () != TARGET_WAITKIND_STOPPED
- || ws.sig () != GDB_SIGNAL_TRAP)
- return 0;
- return breakpoint_address_match_range (bl->pspace->aspace, bl->address,
- bl->length, aspace, bp_addr);
- }
- /* Implement the "resources_needed" breakpoint_ops method for
- ranged breakpoints. */
- static int
- resources_needed_ranged_breakpoint (const struct bp_location *bl)
- {
- return target_ranged_break_num_registers ();
- }
- /* Implement the "print_it" breakpoint_ops method for
- ranged breakpoints. */
- static enum print_stop_action
- print_it_ranged_breakpoint (bpstat *bs)
- {
- struct breakpoint *b = bs->breakpoint_at;
- struct bp_location *bl = b->loc;
- struct ui_out *uiout = current_uiout;
- gdb_assert (b->type == bp_hardware_breakpoint);
- /* Ranged breakpoints have only one location. */
- gdb_assert (bl && bl->next == NULL);
- annotate_breakpoint (b->number);
- maybe_print_thread_hit_breakpoint (uiout);
- if (b->disposition == disp_del)
- uiout->text ("Temporary ranged breakpoint ");
- else
- uiout->text ("Ranged breakpoint ");
- if (uiout->is_mi_like_p ())
- {
- uiout->field_string ("reason",
- async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
- uiout->field_string ("disp", bpdisp_text (b->disposition));
- }
- uiout->field_signed ("bkptno", b->number);
- uiout->text (", ");
- return PRINT_SRC_AND_LOC;
- }
- /* Implement the "print_one" breakpoint_ops method for
- ranged breakpoints. */
- static void
- print_one_ranged_breakpoint (struct breakpoint *b,
- struct bp_location **last_loc)
- {
- struct bp_location *bl = b->loc;
- struct value_print_options opts;
- struct ui_out *uiout = current_uiout;
- /* Ranged breakpoints have only one location. */
- gdb_assert (bl && bl->next == NULL);
- get_user_print_options (&opts);
- if (opts.addressprint)
- /* We don't print the address range here, it will be printed later
- by print_one_detail_ranged_breakpoint. */
- uiout->field_skip ("addr");
- annotate_field (5);
- print_breakpoint_location (b, bl);
- *last_loc = bl;
- }
- /* Implement the "print_one_detail" breakpoint_ops method for
- ranged breakpoints. */
- static void
- print_one_detail_ranged_breakpoint (const struct breakpoint *b,
- struct ui_out *uiout)
- {
- CORE_ADDR address_start, address_end;
- struct bp_location *bl = b->loc;
- string_file stb;
- gdb_assert (bl);
- address_start = bl->address;
- address_end = address_start + bl->length - 1;
- uiout->text ("\taddress range: ");
- stb.printf ("[%s, %s]",
- print_core_address (bl->gdbarch, address_start),
- print_core_address (bl->gdbarch, address_end));
- uiout->field_stream ("addr", stb);
- uiout->text ("\n");
- }
- /* Implement the "print_mention" breakpoint_ops method for
- ranged breakpoints. */
- static void
- print_mention_ranged_breakpoint (struct breakpoint *b)
- {
- struct bp_location *bl = b->loc;
- struct ui_out *uiout = current_uiout;
- gdb_assert (bl);
- gdb_assert (b->type == bp_hardware_breakpoint);
- uiout->message (_("Hardware assisted ranged breakpoint %d from %s to %s."),
- b->number, paddress (bl->gdbarch, bl->address),
- paddress (bl->gdbarch, bl->address + bl->length - 1));
- }
- /* Implement the "print_recreate" breakpoint_ops method for
- ranged breakpoints. */
- static void
- print_recreate_ranged_breakpoint (struct breakpoint *b, struct ui_file *fp)
- {
- gdb_printf (fp, "break-range %s, %s",
- event_location_to_string (b->location.get ()),
- event_location_to_string (b->location_range_end.get ()));
- print_recreate_thread (b, fp);
- }
- /* The breakpoint_ops structure to be used in ranged breakpoints. */
- static struct breakpoint_ops ranged_breakpoint_ops;
- /* Find the address where the end of the breakpoint range should be
- placed, given the SAL of the end of the range. This is so that if
- the user provides a line number, the end of the range is set to the
- last instruction of the given line. */
- static CORE_ADDR
- find_breakpoint_range_end (struct symtab_and_line sal)
- {
- CORE_ADDR end;
- /* If the user provided a PC value, use it. Otherwise,
- find the address of the end of the given location. */
- if (sal.explicit_pc)
- end = sal.pc;
- else
- {
- int ret;
- CORE_ADDR start;
- ret = find_line_pc_range (sal, &start, &end);
- if (!ret)
- error (_("Could not find location of the end of the range."));
- /* find_line_pc_range returns the start of the next line. */
- end--;
- }
- return end;
- }
- /* Implement the "break-range" CLI command. */
- static void
- break_range_command (const char *arg, int from_tty)
- {
- const char *arg_start;
- struct linespec_result canonical_start, canonical_end;
- int bp_count, can_use_bp, length;
- CORE_ADDR end;
- struct breakpoint *b;
- /* We don't support software ranged breakpoints. */
- if (target_ranged_break_num_registers () < 0)
- error (_("This target does not support hardware ranged breakpoints."));
- bp_count = hw_breakpoint_used_count ();
- bp_count += target_ranged_break_num_registers ();
- can_use_bp = target_can_use_hardware_watchpoint (bp_hardware_breakpoint,
- bp_count, 0);
- if (can_use_bp < 0)
- error (_("Hardware breakpoints used exceeds limit."));
- arg = skip_spaces (arg);
- if (arg == NULL || arg[0] == '\0')
- error(_("No address range specified."));
- arg_start = arg;
- event_location_up start_location = string_to_event_location (&arg,
- current_language);
- parse_breakpoint_sals (start_location.get (), &canonical_start);
- if (arg[0] != ',')
- error (_("Too few arguments."));
- else if (canonical_start.lsals.empty ())
- error (_("Could not find location of the beginning of the range."));
- const linespec_sals &lsal_start = canonical_start.lsals[0];
- if (canonical_start.lsals.size () > 1
- || lsal_start.sals.size () != 1)
- error (_("Cannot create a ranged breakpoint with multiple locations."));
- const symtab_and_line &sal_start = lsal_start.sals[0];
- std::string addr_string_start (arg_start, arg - arg_start);
- arg++; /* Skip the comma. */
- arg = skip_spaces (arg);
- /* Parse the end location. */
- arg_start = arg;
- /* We call decode_line_full directly here instead of using
- parse_breakpoint_sals because we need to specify the start location's
- symtab and line as the default symtab and line for the end of the
- range. This makes it possible to have ranges like "foo.c:27, +14",
- where +14 means 14 lines from the start location. */
- event_location_up end_location = string_to_event_location (&arg,
- current_language);
- decode_line_full (end_location.get (), DECODE_LINE_FUNFIRSTLINE, NULL,
- sal_start.symtab, sal_start.line,
- &canonical_end, NULL, NULL);
- if (canonical_end.lsals.empty ())
- error (_("Could not find location of the end of the range."));
- const linespec_sals &lsal_end = canonical_end.lsals[0];
- if (canonical_end.lsals.size () > 1
- || lsal_end.sals.size () != 1)
- error (_("Cannot create a ranged breakpoint with multiple locations."));
- const symtab_and_line &sal_end = lsal_end.sals[0];
- end = find_breakpoint_range_end (sal_end);
- if (sal_start.pc > end)
- error (_("Invalid address range, end precedes start."));
- length = end - sal_start.pc + 1;
- if (length < 0)
- /* Length overflowed. */
- error (_("Address range too large."));
- else if (length == 1)
- {
- /* This range is simple enough to be handled by
- the `hbreak' command. */
- hbreak_command (&addr_string_start[0], 1);
- return;
- }
- /* Now set up the breakpoint. */
- b = set_raw_breakpoint (get_current_arch (), sal_start,
- bp_hardware_breakpoint, &ranged_breakpoint_ops);
- set_breakpoint_count (breakpoint_count + 1);
- b->number = breakpoint_count;
- b->disposition = disp_donttouch;
- b->location = std::move (start_location);
- b->location_range_end = std::move (end_location);
- b->loc->length = length;
- mention (b);
- gdb::observers::breakpoint_created.notify (b);
- update_global_location_list (UGLL_MAY_INSERT);
- }
- /* Return non-zero if EXP is verified as constant. Returned zero
- means EXP is variable. Also the constant detection may fail for
- some constant expressions and in such case still falsely return
- zero. */
- static bool
- watchpoint_exp_is_const (const struct expression *exp)
- {
- return exp->op->constant_p ();
- }
- /* Implement the "re_set" breakpoint_ops method for watchpoints. */
- static void
- re_set_watchpoint (struct breakpoint *b)
- {
- struct watchpoint *w = (struct watchpoint *) b;
- /* Watchpoint can be either on expression using entirely global
- variables, or it can be on local variables.
- Watchpoints of the first kind are never auto-deleted, and even
- persist across program restarts. Since they can use variables
- from shared libraries, we need to reparse expression as libraries
- are loaded and unloaded.
- Watchpoints on local variables can also change meaning as result
- of solib event. For example, if a watchpoint uses both a local
- and a global variables in expression, it's a local watchpoint,
- but unloading of a shared library will make the expression
- invalid. This is not a very common use case, but we still
- re-evaluate expression, to avoid surprises to the user.
- Note that for local watchpoints, we re-evaluate it only if
- watchpoints frame id is still valid. If it's not, it means the
- watchpoint is out of scope and will be deleted soon. In fact,
- I'm not sure we'll ever be called in this case.
- If a local watchpoint's frame id is still valid, then
- w->exp_valid_block is likewise valid, and we can safely use it.
- Don't do anything about disabled watchpoints, since they will be
- reevaluated again when enabled. */
- update_watchpoint (w, 1 /* reparse */);
- }
- /* Implement the "insert" breakpoint_ops method for hardware watchpoints. */
- static int
- insert_watchpoint (struct bp_location *bl)
- {
- struct watchpoint *w = (struct watchpoint *) bl->owner;
- int length = w->exact ? 1 : bl->length;
- return target_insert_watchpoint (bl->address, length, bl->watchpoint_type,
- w->cond_exp.get ());
- }
- /* Implement the "remove" breakpoint_ops method for hardware watchpoints. */
- static int
- remove_watchpoint (struct bp_location *bl, enum remove_bp_reason reason)
- {
- struct watchpoint *w = (struct watchpoint *) bl->owner;
- int length = w->exact ? 1 : bl->length;
- return target_remove_watchpoint (bl->address, length, bl->watchpoint_type,
- w->cond_exp.get ());
- }
- static int
- breakpoint_hit_watchpoint (const struct bp_location *bl,
- const address_space *aspace, CORE_ADDR bp_addr,
- const target_waitstatus &ws)
- {
- struct breakpoint *b = bl->owner;
- struct watchpoint *w = (struct watchpoint *) b;
- /* Continuable hardware watchpoints are treated as non-existent if the
- reason we stopped wasn't a hardware watchpoint (we didn't stop on
- some data address). Otherwise gdb won't stop on a break instruction
- in the code (not from a breakpoint) when a hardware watchpoint has
- been defined. Also skip watchpoints which we know did not trigger
- (did not match the data address). */
- if (is_hardware_watchpoint (b)
- && w->watchpoint_triggered == watch_triggered_no)
- return 0;
- return 1;
- }
- static void
- check_status_watchpoint (bpstat *bs)
- {
- gdb_assert (is_watchpoint (bs->breakpoint_at));
- bpstat_check_watchpoint (bs);
- }
- /* Implement the "resources_needed" breakpoint_ops method for
- hardware watchpoints. */
- static int
- resources_needed_watchpoint (const struct bp_location *bl)
- {
- struct watchpoint *w = (struct watchpoint *) bl->owner;
- int length = w->exact? 1 : bl->length;
- return target_region_ok_for_hw_watchpoint (bl->address, length);
- }
- /* Implement the "works_in_software_mode" breakpoint_ops method for
- hardware watchpoints. */
- static int
- works_in_software_mode_watchpoint (const struct breakpoint *b)
- {
- /* Read and access watchpoints only work with hardware support. */
- return b->type == bp_watchpoint || b->type == bp_hardware_watchpoint;
- }
- static enum print_stop_action
- print_it_watchpoint (bpstat *bs)
- {
- struct breakpoint *b;
- enum print_stop_action result;
- struct watchpoint *w;
- struct ui_out *uiout = current_uiout;
- gdb_assert (bs->bp_location_at != NULL);
- b = bs->breakpoint_at;
- w = (struct watchpoint *) b;
- annotate_watchpoint (b->number);
- maybe_print_thread_hit_breakpoint (uiout);
- string_file stb;
- gdb::optional<ui_out_emit_tuple> tuple_emitter;
- switch (b->type)
- {
- case bp_watchpoint:
- case bp_hardware_watchpoint:
- if (uiout->is_mi_like_p ())
- uiout->field_string
- ("reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
- mention (b);
- tuple_emitter.emplace (uiout, "value");
- uiout->text ("\nOld value = ");
- watchpoint_value_print (bs->old_val.get (), &stb);
- uiout->field_stream ("old", stb);
- uiout->text ("\nNew value = ");
- watchpoint_value_print (w->val.get (), &stb);
- uiout->field_stream ("new", stb);
- uiout->text ("\n");
- /* More than one watchpoint may have been triggered. */
- result = PRINT_UNKNOWN;
- break;
- case bp_read_watchpoint:
- if (uiout->is_mi_like_p ())
- uiout->field_string
- ("reason", async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
- mention (b);
- tuple_emitter.emplace (uiout, "value");
- uiout->text ("\nValue = ");
- watchpoint_value_print (w->val.get (), &stb);
- uiout->field_stream ("value", stb);
- uiout->text ("\n");
- result = PRINT_UNKNOWN;
- break;
- case bp_access_watchpoint:
- if (bs->old_val != NULL)
- {
- if (uiout->is_mi_like_p ())
- uiout->field_string
- ("reason",
- async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
- mention (b);
- tuple_emitter.emplace (uiout, "value");
- uiout->text ("\nOld value = ");
- watchpoint_value_print (bs->old_val.get (), &stb);
- uiout->field_stream ("old", stb);
- uiout->text ("\nNew value = ");
- }
- else
- {
- mention (b);
- if (uiout->is_mi_like_p ())
- uiout->field_string
- ("reason",
- async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
- tuple_emitter.emplace (uiout, "value");
- uiout->text ("\nValue = ");
- }
- watchpoint_value_print (w->val.get (), &stb);
- uiout->field_stream ("new", stb);
- uiout->text ("\n");
- result = PRINT_UNKNOWN;
- break;
- default:
- result = PRINT_UNKNOWN;
- }
- return result;
- }
- /* Implement the "print_mention" breakpoint_ops method for hardware
- watchpoints. */
- static void
- print_mention_watchpoint (struct breakpoint *b)
- {
- struct watchpoint *w = (struct watchpoint *) b;
- struct ui_out *uiout = current_uiout;
- const char *tuple_name;
- switch (b->type)
- {
- case bp_watchpoint:
- uiout->text ("Watchpoint ");
- tuple_name = "wpt";
- break;
- case bp_hardware_watchpoint:
- uiout->text ("Hardware watchpoint ");
- tuple_name = "wpt";
- break;
- case bp_read_watchpoint:
- uiout->text ("Hardware read watchpoint ");
- tuple_name = "hw-rwpt";
- break;
- case bp_access_watchpoint:
- uiout->text ("Hardware access (read/write) watchpoint ");
- tuple_name = "hw-awpt";
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("Invalid hardware watchpoint type."));
- }
- ui_out_emit_tuple tuple_emitter (uiout, tuple_name);
- uiout->field_signed ("number", b->number);
- uiout->text (": ");
- uiout->field_string ("exp", w->exp_string.get ());
- }
- /* Implement the "print_recreate" breakpoint_ops method for
- watchpoints. */
- static void
- print_recreate_watchpoint (struct breakpoint *b, struct ui_file *fp)
- {
- struct watchpoint *w = (struct watchpoint *) b;
- switch (b->type)
- {
- case bp_watchpoint:
- case bp_hardware_watchpoint:
- gdb_printf (fp, "watch");
- break;
- case bp_read_watchpoint:
- gdb_printf (fp, "rwatch");
- break;
- case bp_access_watchpoint:
- gdb_printf (fp, "awatch");
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("Invalid watchpoint type."));
- }
- gdb_printf (fp, " %s", w->exp_string.get ());
- print_recreate_thread (b, fp);
- }
- /* Implement the "explains_signal" breakpoint_ops method for
- watchpoints. */
- static int
- explains_signal_watchpoint (struct breakpoint *b, enum gdb_signal sig)
- {
- /* A software watchpoint cannot cause a signal other than
- GDB_SIGNAL_TRAP. */
- if (b->type == bp_watchpoint && sig != GDB_SIGNAL_TRAP)
- return 0;
- return 1;
- }
- /* The breakpoint_ops structure to be used in hardware watchpoints. */
- static struct breakpoint_ops watchpoint_breakpoint_ops;
- /* Implement the "insert" breakpoint_ops method for
- masked hardware watchpoints. */
- static int
- insert_masked_watchpoint (struct bp_location *bl)
- {
- struct watchpoint *w = (struct watchpoint *) bl->owner;
- return target_insert_mask_watchpoint (bl->address, w->hw_wp_mask,
- bl->watchpoint_type);
- }
- /* Implement the "remove" breakpoint_ops method for
- masked hardware watchpoints. */
- static int
- remove_masked_watchpoint (struct bp_location *bl, enum remove_bp_reason reason)
- {
- struct watchpoint *w = (struct watchpoint *) bl->owner;
- return target_remove_mask_watchpoint (bl->address, w->hw_wp_mask,
- bl->watchpoint_type);
- }
- /* Implement the "resources_needed" breakpoint_ops method for
- masked hardware watchpoints. */
- static int
- resources_needed_masked_watchpoint (const struct bp_location *bl)
- {
- struct watchpoint *w = (struct watchpoint *) bl->owner;
- return target_masked_watch_num_registers (bl->address, w->hw_wp_mask);
- }
- /* Implement the "works_in_software_mode" breakpoint_ops method for
- masked hardware watchpoints. */
- static int
- works_in_software_mode_masked_watchpoint (const struct breakpoint *b)
- {
- return 0;
- }
- /* Implement the "print_it" breakpoint_ops method for
- masked hardware watchpoints. */
- static enum print_stop_action
- print_it_masked_watchpoint (bpstat *bs)
- {
- struct breakpoint *b = bs->breakpoint_at;
- struct ui_out *uiout = current_uiout;
- /* Masked watchpoints have only one location. */
- gdb_assert (b->loc && b->loc->next == NULL);
- annotate_watchpoint (b->number);
- maybe_print_thread_hit_breakpoint (uiout);
- switch (b->type)
- {
- case bp_hardware_watchpoint:
- if (uiout->is_mi_like_p ())
- uiout->field_string
- ("reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
- break;
- case bp_read_watchpoint:
- if (uiout->is_mi_like_p ())
- uiout->field_string
- ("reason", async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
- break;
- case bp_access_watchpoint:
- if (uiout->is_mi_like_p ())
- uiout->field_string
- ("reason",
- async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("Invalid hardware watchpoint type."));
- }
- mention (b);
- uiout->text (_("\n\
- Check the underlying instruction at PC for the memory\n\
- address and value which triggered this watchpoint.\n"));
- uiout->text ("\n");
- /* More than one watchpoint may have been triggered. */
- return PRINT_UNKNOWN;
- }
- /* Implement the "print_one_detail" breakpoint_ops method for
- masked hardware watchpoints. */
- static void
- print_one_detail_masked_watchpoint (const struct breakpoint *b,
- struct ui_out *uiout)
- {
- struct watchpoint *w = (struct watchpoint *) b;
- /* Masked watchpoints have only one location. */
- gdb_assert (b->loc && b->loc->next == NULL);
- uiout->text ("\tmask ");
- uiout->field_core_addr ("mask", b->loc->gdbarch, w->hw_wp_mask);
- uiout->text ("\n");
- }
- /* Implement the "print_mention" breakpoint_ops method for
- masked hardware watchpoints. */
- static void
- print_mention_masked_watchpoint (struct breakpoint *b)
- {
- struct watchpoint *w = (struct watchpoint *) b;
- struct ui_out *uiout = current_uiout;
- const char *tuple_name;
- switch (b->type)
- {
- case bp_hardware_watchpoint:
- uiout->text ("Masked hardware watchpoint ");
- tuple_name = "wpt";
- break;
- case bp_read_watchpoint:
- uiout->text ("Masked hardware read watchpoint ");
- tuple_name = "hw-rwpt";
- break;
- case bp_access_watchpoint:
- uiout->text ("Masked hardware access (read/write) watchpoint ");
- tuple_name = "hw-awpt";
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("Invalid hardware watchpoint type."));
- }
- ui_out_emit_tuple tuple_emitter (uiout, tuple_name);
- uiout->field_signed ("number", b->number);
- uiout->text (": ");
- uiout->field_string ("exp", w->exp_string.get ());
- }
- /* Implement the "print_recreate" breakpoint_ops method for
- masked hardware watchpoints. */
- static void
- print_recreate_masked_watchpoint (struct breakpoint *b, struct ui_file *fp)
- {
- struct watchpoint *w = (struct watchpoint *) b;
- switch (b->type)
- {
- case bp_hardware_watchpoint:
- gdb_printf (fp, "watch");
- break;
- case bp_read_watchpoint:
- gdb_printf (fp, "rwatch");
- break;
- case bp_access_watchpoint:
- gdb_printf (fp, "awatch");
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("Invalid hardware watchpoint type."));
- }
- gdb_printf (fp, " %s mask 0x%s", w->exp_string.get (),
- phex (w->hw_wp_mask, sizeof (CORE_ADDR)));
- print_recreate_thread (b, fp);
- }
- /* The breakpoint_ops structure to be used in masked hardware watchpoints. */
- static struct breakpoint_ops masked_watchpoint_breakpoint_ops;
- /* Tell whether the given watchpoint is a masked hardware watchpoint. */
- static bool
- is_masked_watchpoint (const struct breakpoint *b)
- {
- return b->ops == &masked_watchpoint_breakpoint_ops;
- }
- /* accessflag: hw_write: watch write,
- hw_read: watch read,
- hw_access: watch access (read or write) */
- static void
- watch_command_1 (const char *arg, int accessflag, int from_tty,
- bool just_location, bool internal)
- {
- struct breakpoint *scope_breakpoint = NULL;
- const struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL;
- struct value *result;
- int saved_bitpos = 0, saved_bitsize = 0;
- const char *exp_start = NULL;
- const char *exp_end = NULL;
- const char *tok, *end_tok;
- int toklen = -1;
- const char *cond_start = NULL;
- const char *cond_end = NULL;
- enum bptype bp_type;
- int thread = -1;
- /* Flag to indicate whether we are going to use masks for
- the hardware watchpoint. */
- bool use_mask = false;
- CORE_ADDR mask = 0;
- int task = 0;
- /* Make sure that we actually have parameters to parse. */
- if (arg != NULL && arg[0] != '\0')
- {
- const char *value_start;
- exp_end = arg + strlen (arg);
- /* Look for "parameter value" pairs at the end
- of the arguments string. */
- for (tok = exp_end - 1; tok > arg; tok--)
- {
- /* Skip whitespace at the end of the argument list. */
- while (tok > arg && (*tok == ' ' || *tok == '\t'))
- tok--;
- /* Find the beginning of the last token.
- This is the value of the parameter. */
- while (tok > arg && (*tok != ' ' && *tok != '\t'))
- tok--;
- value_start = tok + 1;
- /* Skip whitespace. */
- while (tok > arg && (*tok == ' ' || *tok == '\t'))
- tok--;
- end_tok = tok;
- /* Find the beginning of the second to last token.
- This is the parameter itself. */
- while (tok > arg && (*tok != ' ' && *tok != '\t'))
- tok--;
- tok++;
- toklen = end_tok - tok + 1;
- if (toklen == 6 && startswith (tok, "thread"))
- {
- struct thread_info *thr;
- /* At this point we've found a "thread" token, which means
- the user is trying to set a watchpoint that triggers
- only in a specific thread. */
- const char *endp;
- if (thread != -1)
- error(_("You can specify only one thread."));
- /* Extract the thread ID from the next token. */
- thr = parse_thread_id (value_start, &endp);
- /* Check if the user provided a valid thread ID. */
- if (*endp != ' ' && *endp != '\t' && *endp != '\0')
- invalid_thread_id_error (value_start);
- thread = thr->global_num;
- }
- else if (toklen == 4 && startswith (tok, "task"))
- {
- char *tmp;
- task = strtol (value_start, &tmp, 0);
- if (tmp == value_start)
- error (_("Junk after task keyword."));
- if (!valid_task_id (task))
- error (_("Unknown task %d."), task);
- }
- else if (toklen == 4 && startswith (tok, "mask"))
- {
- /* We've found a "mask" token, which means the user wants to
- create a hardware watchpoint that is going to have the mask
- facility. */
- struct value *mask_value, *mark;
- if (use_mask)
- error(_("You can specify only one mask."));
- use_mask = just_location = true;
- mark = value_mark ();
- mask_value = parse_to_comma_and_eval (&value_start);
- mask = value_as_address (mask_value);
- value_free_to_mark (mark);
- }
- else
- /* We didn't recognize what we found. We should stop here. */
- break;
- /* Truncate the string and get rid of the "parameter value" pair before
- the arguments string is parsed by the parse_exp_1 function. */
- exp_end = tok;
- }
- }
- else
- exp_end = arg;
- /* Parse the rest of the arguments. From here on out, everything
- is in terms of a newly allocated string instead of the original
- ARG. */
- std::string expression (arg, exp_end - arg);
- exp_start = arg = expression.c_str ();
- innermost_block_tracker tracker;
- expression_up exp = parse_exp_1 (&arg, 0, 0, 0, &tracker);
- exp_end = arg;
- /* Remove trailing whitespace from the expression before saving it.
- This makes the eventual display of the expression string a bit
- prettier. */
- while (exp_end > exp_start && (exp_end[-1] == ' ' || exp_end[-1] == '\t'))
- --exp_end;
- /* Checking if the expression is not constant. */
- if (watchpoint_exp_is_const (exp.get ()))
- {
- int len;
- len = exp_end - exp_start;
- while (len > 0 && isspace (exp_start[len - 1]))
- len--;
- error (_("Cannot watch constant value `%.*s'."), len, exp_start);
- }
- exp_valid_block = tracker.block ();
- struct value *mark = value_mark ();
- struct value *val_as_value = nullptr;
- fetch_subexp_value (exp.get (), exp->op.get (), &val_as_value, &result, NULL,
- just_location);
- if (val_as_value != NULL && just_location)
- {
- saved_bitpos = value_bitpos (val_as_value);
- saved_bitsize = value_bitsize (val_as_value);
- }
- value_ref_ptr val;
- if (just_location)
- {
- int ret;
- exp_valid_block = NULL;
- val = release_value (value_addr (result));
- value_free_to_mark (mark);
- if (use_mask)
- {
- ret = target_masked_watch_num_registers (value_as_address (val.get ()),
- mask);
- if (ret == -1)
- error (_("This target does not support masked watchpoints."));
- else if (ret == -2)
- error (_("Invalid mask or memory region."));
- }
- }
- else if (val_as_value != NULL)
- val = release_value (val_as_value);
- tok = skip_spaces (arg);
- end_tok = skip_to_space (tok);
- toklen = end_tok - tok;
- if (toklen >= 1 && strncmp (tok, "if", toklen) == 0)
- {
- tok = cond_start = end_tok + 1;
- innermost_block_tracker if_tracker;
- parse_exp_1 (&tok, 0, 0, 0, &if_tracker);
- /* The watchpoint expression may not be local, but the condition
- may still be. E.g.: `watch global if local > 0'. */
- cond_exp_valid_block = if_tracker.block ();
- cond_end = tok;
- }
- if (*tok)
- error (_("Junk at end of command."));
- frame_info *wp_frame = block_innermost_frame (exp_valid_block);
- /* Save this because create_internal_breakpoint below invalidates
- 'wp_frame'. */
- frame_id watchpoint_frame = get_frame_id (wp_frame);
- /* If the expression is "local", then set up a "watchpoint scope"
- breakpoint at the point where we've left the scope of the watchpoint
- expression. Create the scope breakpoint before the watchpoint, so
- that we will encounter it first in bpstat_stop_status. */
- if (exp_valid_block != NULL && wp_frame != NULL)
- {
- frame_id caller_frame_id = frame_unwind_caller_id (wp_frame);
- if (frame_id_p (caller_frame_id))
- {
- gdbarch *caller_arch = frame_unwind_caller_arch (wp_frame);
- CORE_ADDR caller_pc = frame_unwind_caller_pc (wp_frame);
- scope_breakpoint
- = create_internal_breakpoint (caller_arch, caller_pc,
- bp_watchpoint_scope,
- &momentary_breakpoint_ops);
- /* create_internal_breakpoint could invalidate WP_FRAME. */
- wp_frame = NULL;
- scope_breakpoint->enable_state = bp_enabled;
- /* Automatically delete the breakpoint when it hits. */
- scope_breakpoint->disposition = disp_del;
- /* Only break in the proper frame (help with recursion). */
- scope_breakpoint->frame_id = caller_frame_id;
- /* Set the address at which we will stop. */
- scope_breakpoint->loc->gdbarch = caller_arch;
- scope_breakpoint->loc->requested_address = caller_pc;
- scope_breakpoint->loc->address
- = adjust_breakpoint_address (scope_breakpoint->loc->gdbarch,
- scope_breakpoint->loc->requested_address,
- scope_breakpoint->type);
- }
- }
- /* Now set up the breakpoint. We create all watchpoints as hardware
- watchpoints here even if hardware watchpoints are turned off, a call
- to update_watchpoint later in this function will cause the type to
- drop back to bp_watchpoint (software watchpoint) if required. */
- if (accessflag == hw_read)
- bp_type = bp_read_watchpoint;
- else if (accessflag == hw_access)
- bp_type = bp_access_watchpoint;
- else
- bp_type = bp_hardware_watchpoint;
- std::unique_ptr<watchpoint> w (new watchpoint ());
- if (use_mask)
- init_raw_breakpoint_without_location (w.get (), NULL, bp_type,
- &masked_watchpoint_breakpoint_ops);
- else
- init_raw_breakpoint_without_location (w.get (), NULL, bp_type,
- &watchpoint_breakpoint_ops);
- w->thread = thread;
- w->task = task;
- w->disposition = disp_donttouch;
- w->pspace = current_program_space;
- w->exp = std::move (exp);
- w->exp_valid_block = exp_valid_block;
- w->cond_exp_valid_block = cond_exp_valid_block;
- if (just_location)
- {
- struct type *t = value_type (val.get ());
- CORE_ADDR addr = value_as_address (val.get ());
- w->exp_string_reparse
- = current_language->watch_location_expression (t, addr);
- w->exp_string = xstrprintf ("-location %.*s",
- (int) (exp_end - exp_start), exp_start);
- }
- else
- w->exp_string.reset (savestring (exp_start, exp_end - exp_start));
- if (use_mask)
- {
- w->hw_wp_mask = mask;
- }
- else
- {
- w->val = val;
- w->val_bitpos = saved_bitpos;
- w->val_bitsize = saved_bitsize;
- w->val_valid = true;
- }
- if (cond_start)
- w->cond_string.reset (savestring (cond_start, cond_end - cond_start));
- else
- w->cond_string = 0;
- if (frame_id_p (watchpoint_frame))
- {
- w->watchpoint_frame = watchpoint_frame;
- w->watchpoint_thread = inferior_ptid;
- }
- else
- {
- w->watchpoint_frame = null_frame_id;
- w->watchpoint_thread = null_ptid;
- }
- if (scope_breakpoint != NULL)
- {
- /* The scope breakpoint is related to the watchpoint. We will
- need to act on them together. */
- w->related_breakpoint = scope_breakpoint;
- scope_breakpoint->related_breakpoint = w.get ();
- }
- if (!just_location)
- value_free_to_mark (mark);
- /* Finally update the new watchpoint. This creates the locations
- that should be inserted. */
- update_watchpoint (w.get (), 1);
- install_breakpoint (internal, std::move (w), 1);
- }
- /* Return count of debug registers needed to watch the given expression.
- If the watchpoint cannot be handled in hardware return zero. */
- static int
- can_use_hardware_watchpoint (const std::vector<value_ref_ptr> &vals)
- {
- int found_memory_cnt = 0;
- /* Did the user specifically forbid us to use hardware watchpoints? */
- if (!can_use_hw_watchpoints)
- return 0;
- gdb_assert (!vals.empty ());
- struct value *head = vals[0].get ();
- /* Make sure that the value of the expression depends only upon
- memory contents, and values computed from them within GDB. If we
- find any register references or function calls, we can't use a
- hardware watchpoint.
- The idea here is that evaluating an expression generates a series
- of values, one holding the value of every subexpression. (The
- expression a*b+c has five subexpressions: a, b, a*b, c, and
- a*b+c.) GDB's values hold almost enough information to establish
- the criteria given above --- they identify memory lvalues,
- register lvalues, computed values, etcetera. So we can evaluate
- the expression, and then scan the chain of values that leaves
- behind to decide whether we can detect any possible change to the
- expression's final value using only hardware watchpoints.
- However, I don't think that the values returned by inferior
- function calls are special in any way. So this function may not
- notice that an expression involving an inferior function call
- can't be watched with hardware watchpoints. FIXME. */
- for (const value_ref_ptr &iter : vals)
- {
- struct value *v = iter.get ();
- if (VALUE_LVAL (v) == lval_memory)
- {
- if (v != head && value_lazy (v))
- /* A lazy memory lvalue in the chain is one that GDB never
- needed to fetch; we either just used its address (e.g.,
- `a' in `a.b') or we never needed it at all (e.g., `a'
- in `a,b'). This doesn't apply to HEAD; if that is
- lazy then it was not readable, but watch it anyway. */
- ;
- else
- {
- /* Ahh, memory we actually used! Check if we can cover
- it with hardware watchpoints. */
- struct type *vtype = check_typedef (value_type (v));
- /* We only watch structs and arrays if user asked for it
- explicitly, never if they just happen to appear in a
- middle of some value chain. */
- if (v == head
- || (vtype->code () != TYPE_CODE_STRUCT
- && vtype->code () != TYPE_CODE_ARRAY))
- {
- CORE_ADDR vaddr = value_address (v);
- int len;
- int num_regs;
- len = (target_exact_watchpoints
- && is_scalar_type_recursive (vtype))?
- 1 : TYPE_LENGTH (value_type (v));
- num_regs = target_region_ok_for_hw_watchpoint (vaddr, len);
- if (!num_regs)
- return 0;
- else
- found_memory_cnt += num_regs;
- }
- }
- }
- else if (VALUE_LVAL (v) != not_lval
- && deprecated_value_modifiable (v) == 0)
- return 0; /* These are values from the history (e.g., $1). */
- else if (VALUE_LVAL (v) == lval_register)
- return 0; /* Cannot watch a register with a HW watchpoint. */
- }
- /* The expression itself looks suitable for using a hardware
- watchpoint, but give the target machine a chance to reject it. */
- return found_memory_cnt;
- }
- void
- watch_command_wrapper (const char *arg, int from_tty, bool internal)
- {
- watch_command_1 (arg, hw_write, from_tty, 0, internal);
- }
- /* Options for the watch, awatch, and rwatch commands. */
- struct watch_options
- {
- /* For -location. */
- bool location = false;
- };
- /* Definitions of options for the "watch", "awatch", and "rwatch" commands.
- Historically GDB always accepted both '-location' and '-l' flags for
- these commands (both flags being synonyms). When converting to the
- newer option scheme only '-location' is added here. That's fine (for
- backward compatibility) as any non-ambiguous prefix of a flag will be
- accepted, so '-l', '-loc', are now all accepted.
- What this means is that, if in the future, we add any new flag here
- that starts with '-l' then this will break backward compatibility, so
- please, don't do that! */
- static const gdb::option::option_def watch_option_defs[] = {
- gdb::option::flag_option_def<watch_options> {
- "location",
- [] (watch_options *opt) { return &opt->location; },
- N_("\
- This evaluates EXPRESSION and watches the memory to which is refers.\n\
- -l can be used as a short form of -location."),
- },
- };
- /* Returns the option group used by 'watch', 'awatch', and 'rwatch'
- commands. */
- static gdb::option::option_def_group
- make_watch_options_def_group (watch_options *opts)
- {
- return {{watch_option_defs}, opts};
- }
- /* A helper function that looks for the "-location" argument and then
- calls watch_command_1. */
- static void
- watch_maybe_just_location (const char *arg, int accessflag, int from_tty)
- {
- watch_options opts;
- auto grp = make_watch_options_def_group (&opts);
- gdb::option::process_options
- (&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
- if (arg != nullptr && *arg == '\0')
- arg = nullptr;
- watch_command_1 (arg, accessflag, from_tty, opts.location, false);
- }
- /* Command completion for 'watch', 'awatch', and 'rwatch' commands. */
- static void
- watch_command_completer (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char * /*word*/)
- {
- const auto group = make_watch_options_def_group (nullptr);
- if (gdb::option::complete_options
- (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
- return;
- const char *word = advance_to_expression_complete_word_point (tracker, text);
- expression_completer (ignore, tracker, text, word);
- }
- static void
- watch_command (const char *arg, int from_tty)
- {
- watch_maybe_just_location (arg, hw_write, from_tty);
- }
- void
- rwatch_command_wrapper (const char *arg, int from_tty, bool internal)
- {
- watch_command_1 (arg, hw_read, from_tty, 0, internal);
- }
- static void
- rwatch_command (const char *arg, int from_tty)
- {
- watch_maybe_just_location (arg, hw_read, from_tty);
- }
- void
- awatch_command_wrapper (const char *arg, int from_tty, bool internal)
- {
- watch_command_1 (arg, hw_access, from_tty, 0, internal);
- }
- static void
- awatch_command (const char *arg, int from_tty)
- {
- watch_maybe_just_location (arg, hw_access, from_tty);
- }
- /* Data for the FSM that manages the until(location)/advance commands
- in infcmd.c. Here because it uses the mechanisms of
- breakpoints. */
- struct until_break_fsm : public thread_fsm
- {
- /* The thread that was current when the command was executed. */
- int thread;
- /* The breakpoint set at the return address in the caller frame,
- plus breakpoints at all the destination locations. */
- std::vector<breakpoint_up> breakpoints;
- until_break_fsm (struct interp *cmd_interp, int thread,
- std::vector<breakpoint_up> &&breakpoints)
- : thread_fsm (cmd_interp),
- thread (thread),
- breakpoints (std::move (breakpoints))
- {
- }
- void clean_up (struct thread_info *thread) override;
- bool should_stop (struct thread_info *thread) override;
- enum async_reply_reason do_async_reply_reason () override;
- };
- /* Implementation of the 'should_stop' FSM method for the
- until(location)/advance commands. */
- bool
- until_break_fsm::should_stop (struct thread_info *tp)
- {
- for (const breakpoint_up &bp : breakpoints)
- if (bpstat_find_breakpoint (tp->control.stop_bpstat,
- bp.get ()) != NULL)
- {
- set_finished ();
- break;
- }
- return true;
- }
- /* Implementation of the 'clean_up' FSM method for the
- until(location)/advance commands. */
- void
- until_break_fsm::clean_up (struct thread_info *)
- {
- /* Clean up our temporary breakpoints. */
- breakpoints.clear ();
- delete_longjmp_breakpoint (thread);
- }
- /* Implementation of the 'async_reply_reason' FSM method for the
- until(location)/advance commands. */
- enum async_reply_reason
- until_break_fsm::do_async_reply_reason ()
- {
- return EXEC_ASYNC_LOCATION_REACHED;
- }
- void
- until_break_command (const char *arg, int from_tty, int anywhere)
- {
- struct frame_info *frame;
- struct gdbarch *frame_gdbarch;
- struct frame_id stack_frame_id;
- struct frame_id caller_frame_id;
- int thread;
- struct thread_info *tp;
- clear_proceed_status (0);
- /* Set a breakpoint where the user wants it and at return from
- this function. */
- event_location_up location = string_to_event_location (&arg, current_language);
- std::vector<symtab_and_line> sals
- = (last_displayed_sal_is_valid ()
- ? decode_line_1 (location.get (), DECODE_LINE_FUNFIRSTLINE, NULL,
- get_last_displayed_symtab (),
- get_last_displayed_line ())
- : decode_line_1 (location.get (), DECODE_LINE_FUNFIRSTLINE,
- NULL, NULL, 0));
- if (sals.empty ())
- error (_("Couldn't get information on specified line."));
- if (*arg)
- error (_("Junk at end of arguments."));
- tp = inferior_thread ();
- thread = tp->global_num;
- /* Note linespec handling above invalidates the frame chain.
- Installing a breakpoint also invalidates the frame chain (as it
- may need to switch threads), so do any frame handling before
- that. */
- frame = get_selected_frame (NULL);
- frame_gdbarch = get_frame_arch (frame);
- stack_frame_id = get_stack_frame_id (frame);
- caller_frame_id = frame_unwind_caller_id (frame);
- /* Keep within the current frame, or in frames called by the current
- one. */
- std::vector<breakpoint_up> breakpoints;
- gdb::optional<delete_longjmp_breakpoint_cleanup> lj_deleter;
- if (frame_id_p (caller_frame_id))
- {
- struct symtab_and_line sal2;
- struct gdbarch *caller_gdbarch;
- sal2 = find_pc_line (frame_unwind_caller_pc (frame), 0);
- sal2.pc = frame_unwind_caller_pc (frame);
- caller_gdbarch = frame_unwind_caller_arch (frame);
- breakpoint_up caller_breakpoint
- = set_momentary_breakpoint (caller_gdbarch, sal2,
- caller_frame_id, bp_until);
- breakpoints.emplace_back (std::move (caller_breakpoint));
- set_longjmp_breakpoint (tp, caller_frame_id);
- lj_deleter.emplace (thread);
- }
- /* set_momentary_breakpoint could invalidate FRAME. */
- frame = NULL;
- /* If the user told us to continue until a specified location, we
- don't specify a frame at which we need to stop. Otherwise,
- specify the selected frame, because we want to stop only at the
- very same frame. */
- frame_id stop_frame_id = anywhere ? null_frame_id : stack_frame_id;
- for (symtab_and_line &sal : sals)
- {
- resolve_sal_pc (&sal);
- breakpoint_up location_breakpoint
- = set_momentary_breakpoint (frame_gdbarch, sal,
- stop_frame_id, bp_until);
- breakpoints.emplace_back (std::move (location_breakpoint));
- }
- tp->set_thread_fsm
- (std::unique_ptr<thread_fsm>
- (new until_break_fsm (command_interp (), tp->global_num,
- std::move (breakpoints))));
- if (lj_deleter)
- lj_deleter->release ();
- proceed (-1, GDB_SIGNAL_DEFAULT);
- }
- void
- init_ada_exception_breakpoint (struct breakpoint *b,
- struct gdbarch *gdbarch,
- struct symtab_and_line sal,
- const char *addr_string,
- const struct breakpoint_ops *ops,
- int tempflag,
- int enabled,
- int from_tty)
- {
- if (from_tty)
- {
- struct gdbarch *loc_gdbarch = get_sal_arch (sal);
- if (!loc_gdbarch)
- loc_gdbarch = gdbarch;
- describe_other_breakpoints (loc_gdbarch,
- sal.pspace, sal.pc, sal.section, -1);
- /* FIXME: brobecker/2006-12-28: Actually, re-implement a special
- version for exception catchpoints, because two catchpoints
- used for different exception names will use the same address.
- In this case, a "breakpoint ... also set at..." warning is
- unproductive. Besides, the warning phrasing is also a bit
- inappropriate, we should use the word catchpoint, and tell
- the user what type of catchpoint it is. The above is good
- enough for now, though. */
- }
- init_raw_breakpoint (b, gdbarch, sal, bp_catchpoint, ops);
- b->enable_state = enabled ? bp_enabled : bp_disabled;
- b->disposition = tempflag ? disp_del : disp_donttouch;
- b->location = string_to_event_location (&addr_string,
- language_def (language_ada));
- b->language = language_ada;
- }
- /* Compare two breakpoints and return a strcmp-like result. */
- static int
- compare_breakpoints (const breakpoint *a, const breakpoint *b)
- {
- uintptr_t ua = (uintptr_t) a;
- uintptr_t ub = (uintptr_t) b;
- if (a->number < b->number)
- return -1;
- else if (a->number > b->number)
- return 1;
- /* Now sort by address, in case we see, e..g, two breakpoints with
- the number 0. */
- if (ua < ub)
- return -1;
- return ua > ub ? 1 : 0;
- }
- /* Delete breakpoints by address or line. */
- static void
- clear_command (const char *arg, int from_tty)
- {
- int default_match;
- std::vector<symtab_and_line> decoded_sals;
- symtab_and_line last_sal;
- gdb::array_view<symtab_and_line> sals;
- if (arg)
- {
- decoded_sals
- = decode_line_with_current_source (arg,
- (DECODE_LINE_FUNFIRSTLINE
- | DECODE_LINE_LIST_MODE));
- default_match = 0;
- sals = decoded_sals;
- }
- else
- {
- /* Set sal's line, symtab, pc, and pspace to the values
- corresponding to the last call to print_frame_info. If the
- codepoint is not valid, this will set all the fields to 0. */
- last_sal = get_last_displayed_sal ();
- if (last_sal.symtab == 0)
- error (_("No source file specified."));
- default_match = 1;
- sals = last_sal;
- }
- /* We don't call resolve_sal_pc here. That's not as bad as it
- seems, because all existing breakpoints typically have both
- file/line and pc set. So, if clear is given file/line, we can
- match this to existing breakpoint without obtaining pc at all.
- We only support clearing given the address explicitly
- present in breakpoint table. Say, we've set breakpoint
- at file:line. There were several PC values for that file:line,
- due to optimization, all in one block.
- We've picked one PC value. If "clear" is issued with another
- PC corresponding to the same file:line, the breakpoint won't
- be cleared. We probably can still clear the breakpoint, but
- since the other PC value is never presented to user, user
- can only find it by guessing, and it does not seem important
- to support that. */
- /* For each line spec given, delete bps which correspond to it. Do
- it in two passes, solely to preserve the current behavior that
- from_tty is forced true if we delete more than one
- breakpoint. */
- std::vector<struct breakpoint *> found;
- for (const auto &sal : sals)
- {
- const char *sal_fullname;
- /* If exact pc given, clear bpts at that pc.
- If line given (pc == 0), clear all bpts on specified line.
- If defaulting, clear all bpts on default line
- or at default pc.
- defaulting sal.pc != 0 tests to do
- 0 1 pc
- 1 1 pc _and_ line
- 0 0 line
- 1 0 <can't happen> */
- sal_fullname = (sal.symtab == NULL
- ? NULL : symtab_to_fullname (sal.symtab));
- /* Find all matching breakpoints and add them to 'found'. */
- for (breakpoint *b : all_breakpoints ())
- {
- int match = 0;
- /* Are we going to delete b? */
- if (b->type != bp_none && !is_watchpoint (b))
- {
- for (bp_location *loc : b->locations ())
- {
- /* If the user specified file:line, don't allow a PC
- match. This matches historical gdb behavior. */
- int pc_match = (!sal.explicit_line
- && sal.pc
- && (loc->pspace == sal.pspace)
- && (loc->address == sal.pc)
- && (!section_is_overlay (loc->section)
- || loc->section == sal.section));
- int line_match = 0;
- if ((default_match || sal.explicit_line)
- && loc->symtab != NULL
- && sal_fullname != NULL
- && sal.pspace == loc->pspace
- && loc->line_number == sal.line
- && filename_cmp (symtab_to_fullname (loc->symtab),
- sal_fullname) == 0)
- line_match = 1;
- if (pc_match || line_match)
- {
- match = 1;
- break;
- }
- }
- }
- if (match)
- found.push_back (b);
- }
- }
- /* Now go thru the 'found' chain and delete them. */
- if (found.empty ())
- {
- if (arg)
- error (_("No breakpoint at %s."), arg);
- else
- error (_("No breakpoint at this line."));
- }
- /* Remove duplicates from the vec. */
- std::sort (found.begin (), found.end (),
- [] (const breakpoint *bp_a, const breakpoint *bp_b)
- {
- return compare_breakpoints (bp_a, bp_b) < 0;
- });
- found.erase (std::unique (found.begin (), found.end (),
- [] (const breakpoint *bp_a, const breakpoint *bp_b)
- {
- return compare_breakpoints (bp_a, bp_b) == 0;
- }),
- found.end ());
- if (found.size () > 1)
- from_tty = 1; /* Always report if deleted more than one. */
- if (from_tty)
- {
- if (found.size () == 1)
- gdb_printf (_("Deleted breakpoint "));
- else
- gdb_printf (_("Deleted breakpoints "));
- }
- for (breakpoint *iter : found)
- {
- if (from_tty)
- gdb_printf ("%d ", iter->number);
- delete_breakpoint (iter);
- }
- if (from_tty)
- gdb_putc ('\n');
- }
- /* Delete breakpoint in BS if they are `delete' breakpoints and
- all breakpoints that are marked for deletion, whether hit or not.
- This is called after any breakpoint is hit, or after errors. */
- void
- breakpoint_auto_delete (bpstat *bs)
- {
- for (; bs; bs = bs->next)
- if (bs->breakpoint_at
- && bs->breakpoint_at->disposition == disp_del
- && bs->stop)
- delete_breakpoint (bs->breakpoint_at);
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->disposition == disp_del_at_next_stop)
- delete_breakpoint (b);
- }
- /* A comparison function for bp_location AP and BP being interfaced to
- std::sort. Sort elements primarily by their ADDRESS (no matter what
- bl_address_is_meaningful says), secondarily by ordering first
- permanent elements and terciarily just ensuring the array is sorted
- stable way despite std::sort being an unstable algorithm. */
- static int
- bp_location_is_less_than (const bp_location *a, const bp_location *b)
- {
- if (a->address != b->address)
- return a->address < b->address;
- /* Sort locations at the same address by their pspace number, keeping
- locations of the same inferior (in a multi-inferior environment)
- grouped. */
- if (a->pspace->num != b->pspace->num)
- return a->pspace->num < b->pspace->num;
- /* Sort permanent breakpoints first. */
- if (a->permanent != b->permanent)
- return a->permanent > b->permanent;
- /* Sort by type in order to make duplicate determination easier.
- See update_global_location_list. This is kept in sync with
- breakpoint_locations_match. */
- if (a->loc_type < b->loc_type)
- return true;
- /* Likewise, for range-breakpoints, sort by length. */
- if (a->loc_type == bp_loc_hardware_breakpoint
- && b->loc_type == bp_loc_hardware_breakpoint
- && a->length < b->length)
- return true;
- /* Make the internal GDB representation stable across GDB runs
- where A and B memory inside GDB can differ. Breakpoint locations of
- the same type at the same address can be sorted in arbitrary order. */
- if (a->owner->number != b->owner->number)
- return a->owner->number < b->owner->number;
- return a < b;
- }
- /* Set bp_locations_placed_address_before_address_max and
- bp_locations_shadow_len_after_address_max according to the current
- content of the bp_locations array. */
- static void
- bp_locations_target_extensions_update (void)
- {
- bp_locations_placed_address_before_address_max = 0;
- bp_locations_shadow_len_after_address_max = 0;
- for (bp_location *bl : all_bp_locations ())
- {
- CORE_ADDR start, end, addr;
- if (!bp_location_has_shadow (bl))
- continue;
- start = bl->target_info.placed_address;
- end = start + bl->target_info.shadow_len;
- gdb_assert (bl->address >= start);
- addr = bl->address - start;
- if (addr > bp_locations_placed_address_before_address_max)
- bp_locations_placed_address_before_address_max = addr;
- /* Zero SHADOW_LEN would not pass bp_location_has_shadow. */
- gdb_assert (bl->address < end);
- addr = end - bl->address;
- if (addr > bp_locations_shadow_len_after_address_max)
- bp_locations_shadow_len_after_address_max = addr;
- }
- }
- /* Download tracepoint locations if they haven't been. */
- static void
- download_tracepoint_locations (void)
- {
- enum tribool can_download_tracepoint = TRIBOOL_UNKNOWN;
- scoped_restore_current_pspace_and_thread restore_pspace_thread;
- for (breakpoint *b : all_tracepoints ())
- {
- struct tracepoint *t;
- int bp_location_downloaded = 0;
- if ((b->type == bp_fast_tracepoint
- ? !may_insert_fast_tracepoints
- : !may_insert_tracepoints))
- continue;
- if (can_download_tracepoint == TRIBOOL_UNKNOWN)
- {
- if (target_can_download_tracepoint ())
- can_download_tracepoint = TRIBOOL_TRUE;
- else
- can_download_tracepoint = TRIBOOL_FALSE;
- }
- if (can_download_tracepoint == TRIBOOL_FALSE)
- break;
- for (bp_location *bl : b->locations ())
- {
- /* In tracepoint, locations are _never_ duplicated, so
- should_be_inserted is equivalent to
- unduplicated_should_be_inserted. */
- if (!should_be_inserted (bl) || bl->inserted)
- continue;
- switch_to_program_space_and_thread (bl->pspace);
- target_download_tracepoint (bl);
- bl->inserted = 1;
- bp_location_downloaded = 1;
- }
- t = (struct tracepoint *) b;
- t->number_on_target = b->number;
- if (bp_location_downloaded)
- gdb::observers::breakpoint_modified.notify (b);
- }
- }
- /* Swap the insertion/duplication state between two locations. */
- static void
- swap_insertion (struct bp_location *left, struct bp_location *right)
- {
- const int left_inserted = left->inserted;
- const int left_duplicate = left->duplicate;
- const int left_needs_update = left->needs_update;
- const struct bp_target_info left_target_info = left->target_info;
- /* Locations of tracepoints can never be duplicated. */
- if (is_tracepoint (left->owner))
- gdb_assert (!left->duplicate);
- if (is_tracepoint (right->owner))
- gdb_assert (!right->duplicate);
- left->inserted = right->inserted;
- left->duplicate = right->duplicate;
- left->needs_update = right->needs_update;
- left->target_info = right->target_info;
- right->inserted = left_inserted;
- right->duplicate = left_duplicate;
- right->needs_update = left_needs_update;
- right->target_info = left_target_info;
- }
- /* Force the re-insertion of the locations at ADDRESS. This is called
- once a new/deleted/modified duplicate location is found and we are evaluating
- conditions on the target's side. Such conditions need to be updated on
- the target. */
- static void
- force_breakpoint_reinsertion (struct bp_location *bl)
- {
- CORE_ADDR address = 0;
- int pspace_num;
- address = bl->address;
- pspace_num = bl->pspace->num;
- /* This is only meaningful if the target is
- evaluating conditions and if the user has
- opted for condition evaluation on the target's
- side. */
- if (gdb_evaluates_breakpoint_condition_p ()
- || !target_supports_evaluation_of_breakpoint_conditions ())
- return;
- /* Flag all breakpoint locations with this address and
- the same program space as the location
- as "its condition has changed". We need to
- update the conditions on the target's side. */
- for (bp_location *loc : all_bp_locations_at_addr (address))
- {
- if (!is_breakpoint (loc->owner)
- || pspace_num != loc->pspace->num)
- continue;
- /* Flag the location appropriately. We use a different state to
- let everyone know that we already updated the set of locations
- with addr bl->address and program space bl->pspace. This is so
- we don't have to keep calling these functions just to mark locations
- that have already been marked. */
- loc->condition_changed = condition_updated;
- /* Free the agent expression bytecode as well. We will compute
- it later on. */
- loc->cond_bytecode.reset ();
- }
- }
- /* Called whether new breakpoints are created, or existing breakpoints
- deleted, to update the global location list and recompute which
- locations are duplicate of which.
- The INSERT_MODE flag determines whether locations may not, may, or
- shall be inserted now. See 'enum ugll_insert_mode' for more
- info. */
- static void
- update_global_location_list (enum ugll_insert_mode insert_mode)
- {
- /* Last breakpoint location address that was marked for update. */
- CORE_ADDR last_addr = 0;
- /* Last breakpoint location program space that was marked for update. */
- int last_pspace_num = -1;
- /* Used in the duplicates detection below. When iterating over all
- bp_locations, points to the first bp_location of a given address.
- Breakpoints and watchpoints of different types are never
- duplicates of each other. Keep one pointer for each type of
- breakpoint/watchpoint, so we only need to loop over all locations
- once. */
- struct bp_location *bp_loc_first; /* breakpoint */
- struct bp_location *wp_loc_first; /* hardware watchpoint */
- struct bp_location *awp_loc_first; /* access watchpoint */
- struct bp_location *rwp_loc_first; /* read watchpoint */
- /* Saved former bp_locations array which we compare against the newly
- built bp_locations from the current state of ALL_BREAKPOINTS. */
- std::vector<bp_location *> old_locations = std::move (bp_locations);
- bp_locations.clear ();
- for (breakpoint *b : all_breakpoints ())
- for (bp_location *loc : b->locations ())
- bp_locations.push_back (loc);
- /* See if we need to "upgrade" a software breakpoint to a hardware
- breakpoint. Do this before deciding whether locations are
- duplicates. Also do this before sorting because sorting order
- depends on location type. */
- for (bp_location *loc : bp_locations)
- if (!loc->inserted && should_be_inserted (loc))
- handle_automatic_hardware_breakpoints (loc);
- std::sort (bp_locations.begin (), bp_locations.end (),
- bp_location_is_less_than);
- bp_locations_target_extensions_update ();
- /* Identify bp_location instances that are no longer present in the
- new list, and therefore should be freed. Note that it's not
- necessary that those locations should be removed from inferior --
- if there's another location at the same address (previously
- marked as duplicate), we don't need to remove/insert the
- location.
-
- LOCP is kept in sync with OLD_LOCP, each pointing to the current
- and former bp_location array state respectively. */
- size_t loc_i = 0;
- for (bp_location *old_loc : old_locations)
- {
- /* Tells if 'old_loc' is found among the new locations. If
- not, we have to free it. */
- int found_object = 0;
- /* Tells if the location should remain inserted in the target. */
- int keep_in_target = 0;
- int removed = 0;
- /* Skip LOCP entries which will definitely never be needed.
- Stop either at or being the one matching OLD_LOC. */
- while (loc_i < bp_locations.size ()
- && bp_locations[loc_i]->address < old_loc->address)
- loc_i++;
- for (size_t loc2_i = loc_i;
- (loc2_i < bp_locations.size ()
- && bp_locations[loc2_i]->address == old_loc->address);
- loc2_i++)
- {
- /* Check if this is a new/duplicated location or a duplicated
- location that had its condition modified. If so, we want to send
- its condition to the target if evaluation of conditions is taking
- place there. */
- if (bp_locations[loc2_i]->condition_changed == condition_modified
- && (last_addr != old_loc->address
- || last_pspace_num != old_loc->pspace->num))
- {
- force_breakpoint_reinsertion (bp_locations[loc2_i]);
- last_pspace_num = old_loc->pspace->num;
- }
- if (bp_locations[loc2_i] == old_loc)
- found_object = 1;
- }
- /* We have already handled this address, update it so that we don't
- have to go through updates again. */
- last_addr = old_loc->address;
- /* Target-side condition evaluation: Handle deleted locations. */
- if (!found_object)
- force_breakpoint_reinsertion (old_loc);
- /* If this location is no longer present, and inserted, look if
- there's maybe a new location at the same address. If so,
- mark that one inserted, and don't remove this one. This is
- needed so that we don't have a time window where a breakpoint
- at certain location is not inserted. */
- if (old_loc->inserted)
- {
- /* If the location is inserted now, we might have to remove
- it. */
- if (found_object && should_be_inserted (old_loc))
- {
- /* The location is still present in the location list,
- and still should be inserted. Don't do anything. */
- keep_in_target = 1;
- }
- else
- {
- /* This location still exists, but it won't be kept in the
- target since it may have been disabled. We proceed to
- remove its target-side condition. */
- /* The location is either no longer present, or got
- disabled. See if there's another location at the
- same address, in which case we don't need to remove
- this one from the target. */
- /* OLD_LOC comes from existing struct breakpoint. */
- if (bl_address_is_meaningful (old_loc))
- {
- for (size_t loc2_i = loc_i;
- (loc2_i < bp_locations.size ()
- && bp_locations[loc2_i]->address == old_loc->address);
- loc2_i++)
- {
- bp_location *loc2 = bp_locations[loc2_i];
- if (loc2 == old_loc)
- continue;
- if (breakpoint_locations_match (loc2, old_loc))
- {
- /* Read watchpoint locations are switched to
- access watchpoints, if the former are not
- supported, but the latter are. */
- if (is_hardware_watchpoint (old_loc->owner))
- {
- gdb_assert (is_hardware_watchpoint (loc2->owner));
- loc2->watchpoint_type = old_loc->watchpoint_type;
- }
- /* loc2 is a duplicated location. We need to check
- if it should be inserted in case it will be
- unduplicated. */
- if (unduplicated_should_be_inserted (loc2))
- {
- swap_insertion (old_loc, loc2);
- keep_in_target = 1;
- break;
- }
- }
- }
- }
- }
- if (!keep_in_target)
- {
- if (remove_breakpoint (old_loc))
- {
- /* This is just about all we can do. We could keep
- this location on the global list, and try to
- remove it next time, but there's no particular
- reason why we will succeed next time.
-
- Note that at this point, old_loc->owner is still
- valid, as delete_breakpoint frees the breakpoint
- only after calling us. */
- gdb_printf (_("warning: Error removing "
- "breakpoint %d\n"),
- old_loc->owner->number);
- }
- removed = 1;
- }
- }
- if (!found_object)
- {
- if (removed && target_is_non_stop_p ()
- && need_moribund_for_location_type (old_loc))
- {
- /* This location was removed from the target. In
- non-stop mode, a race condition is possible where
- we've removed a breakpoint, but stop events for that
- breakpoint are already queued and will arrive later.
- We apply an heuristic to be able to distinguish such
- SIGTRAPs from other random SIGTRAPs: we keep this
- breakpoint location for a bit, and will retire it
- after we see some number of events. The theory here
- is that reporting of events should, "on the average",
- be fair, so after a while we'll see events from all
- threads that have anything of interest, and no longer
- need to keep this breakpoint location around. We
- don't hold locations forever so to reduce chances of
- mistaking a non-breakpoint SIGTRAP for a breakpoint
- SIGTRAP.
- The heuristic failing can be disastrous on
- decr_pc_after_break targets.
- On decr_pc_after_break targets, like e.g., x86-linux,
- if we fail to recognize a late breakpoint SIGTRAP,
- because events_till_retirement has reached 0 too
- soon, we'll fail to do the PC adjustment, and report
- a random SIGTRAP to the user. When the user resumes
- the inferior, it will most likely immediately crash
- with SIGILL/SIGBUS/SIGSEGV, or worse, get silently
- corrupted, because of being resumed e.g., in the
- middle of a multi-byte instruction, or skipped a
- one-byte instruction. This was actually seen happen
- on native x86-linux, and should be less rare on
- targets that do not support new thread events, like
- remote, due to the heuristic depending on
- thread_count.
- Mistaking a random SIGTRAP for a breakpoint trap
- causes similar symptoms (PC adjustment applied when
- it shouldn't), but then again, playing with SIGTRAPs
- behind the debugger's back is asking for trouble.
- Since hardware watchpoint traps are always
- distinguishable from other traps, so we don't need to
- apply keep hardware watchpoint moribund locations
- around. We simply always ignore hardware watchpoint
- traps we can no longer explain. */
- process_stratum_target *proc_target = nullptr;
- for (inferior *inf : all_inferiors ())
- if (inf->pspace == old_loc->pspace)
- {
- proc_target = inf->process_target ();
- break;
- }
- if (proc_target != nullptr)
- old_loc->events_till_retirement
- = 3 * (thread_count (proc_target) + 1);
- else
- old_loc->events_till_retirement = 1;
- old_loc->owner = NULL;
- moribund_locations.push_back (old_loc);
- }
- else
- {
- old_loc->owner = NULL;
- decref_bp_location (&old_loc);
- }
- }
- }
- /* Rescan breakpoints at the same address and section, marking the
- first one as "first" and any others as "duplicates". This is so
- that the bpt instruction is only inserted once. If we have a
- permanent breakpoint at the same place as BPT, make that one the
- official one, and the rest as duplicates. Permanent breakpoints
- are sorted first for the same address.
- Do the same for hardware watchpoints, but also considering the
- watchpoint's type (regular/access/read) and length. */
- bp_loc_first = NULL;
- wp_loc_first = NULL;
- awp_loc_first = NULL;
- rwp_loc_first = NULL;
- for (bp_location *loc : all_bp_locations ())
- {
- /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always
- non-NULL. */
- struct bp_location **loc_first_p;
- breakpoint *b = loc->owner;
- if (!unduplicated_should_be_inserted (loc)
- || !bl_address_is_meaningful (loc)
- /* Don't detect duplicate for tracepoint locations because they are
- never duplicated. See the comments in field `duplicate' of
- `struct bp_location'. */
- || is_tracepoint (b))
- {
- /* Clear the condition modification flag. */
- loc->condition_changed = condition_unchanged;
- continue;
- }
- if (b->type == bp_hardware_watchpoint)
- loc_first_p = &wp_loc_first;
- else if (b->type == bp_read_watchpoint)
- loc_first_p = &rwp_loc_first;
- else if (b->type == bp_access_watchpoint)
- loc_first_p = &awp_loc_first;
- else
- loc_first_p = &bp_loc_first;
- if (*loc_first_p == NULL
- || (overlay_debugging && loc->section != (*loc_first_p)->section)
- || !breakpoint_locations_match (loc, *loc_first_p))
- {
- *loc_first_p = loc;
- loc->duplicate = 0;
- if (is_breakpoint (loc->owner) && loc->condition_changed)
- {
- loc->needs_update = 1;
- /* Clear the condition modification flag. */
- loc->condition_changed = condition_unchanged;
- }
- continue;
- }
- /* This and the above ensure the invariant that the first location
- is not duplicated, and is the inserted one.
- All following are marked as duplicated, and are not inserted. */
- if (loc->inserted)
- swap_insertion (loc, *loc_first_p);
- loc->duplicate = 1;
- /* Clear the condition modification flag. */
- loc->condition_changed = condition_unchanged;
- }
- if (insert_mode == UGLL_INSERT || breakpoints_should_be_inserted_now ())
- {
- if (insert_mode != UGLL_DONT_INSERT)
- insert_breakpoint_locations ();
- else
- {
- /* Even though the caller told us to not insert new
- locations, we may still need to update conditions on the
- target's side of breakpoints that were already inserted
- if the target is evaluating breakpoint conditions. We
- only update conditions for locations that are marked
- "needs_update". */
- update_inserted_breakpoint_locations ();
- }
- }
- if (insert_mode != UGLL_DONT_INSERT)
- download_tracepoint_locations ();
- }
- void
- breakpoint_retire_moribund (void)
- {
- for (int ix = 0; ix < moribund_locations.size (); ++ix)
- {
- struct bp_location *loc = moribund_locations[ix];
- if (--(loc->events_till_retirement) == 0)
- {
- decref_bp_location (&loc);
- unordered_remove (moribund_locations, ix);
- --ix;
- }
- }
- }
- static void
- update_global_location_list_nothrow (enum ugll_insert_mode insert_mode)
- {
- try
- {
- update_global_location_list (insert_mode);
- }
- catch (const gdb_exception_error &e)
- {
- }
- }
- /* Clear BKP from a BPS. */
- static void
- bpstat_remove_bp_location (bpstat *bps, struct breakpoint *bpt)
- {
- bpstat *bs;
- for (bs = bps; bs; bs = bs->next)
- if (bs->breakpoint_at == bpt)
- {
- bs->breakpoint_at = NULL;
- bs->old_val = NULL;
- /* bs->commands will be freed later. */
- }
- }
- /* Callback for iterate_over_threads. */
- static int
- bpstat_remove_breakpoint_callback (struct thread_info *th, void *data)
- {
- struct breakpoint *bpt = (struct breakpoint *) data;
- bpstat_remove_bp_location (th->control.stop_bpstat, bpt);
- return 0;
- }
- /* Helper for breakpoint and tracepoint breakpoint_ops->mention
- callbacks. */
- static void
- say_where (struct breakpoint *b)
- {
- struct value_print_options opts;
- get_user_print_options (&opts);
- /* i18n: cagney/2005-02-11: Below needs to be merged into a
- single string. */
- if (b->loc == NULL)
- {
- /* For pending locations, the output differs slightly based
- on b->extra_string. If this is non-NULL, it contains either
- a condition or dprintf arguments. */
- if (b->extra_string == NULL)
- {
- gdb_printf (_(" (%s) pending."),
- event_location_to_string (b->location.get ()));
- }
- else if (b->type == bp_dprintf)
- {
- gdb_printf (_(" (%s,%s) pending."),
- event_location_to_string (b->location.get ()),
- b->extra_string.get ());
- }
- else
- {
- gdb_printf (_(" (%s %s) pending."),
- event_location_to_string (b->location.get ()),
- b->extra_string.get ());
- }
- }
- else
- {
- if (opts.addressprint || b->loc->symtab == NULL)
- gdb_printf (" at %ps",
- styled_string (address_style.style (),
- paddress (b->loc->gdbarch,
- b->loc->address)));
- if (b->loc->symtab != NULL)
- {
- /* If there is a single location, we can print the location
- more nicely. */
- if (b->loc->next == NULL)
- {
- const char *filename
- = symtab_to_filename_for_display (b->loc->symtab);
- gdb_printf (": file %ps, line %d.",
- styled_string (file_name_style.style (),
- filename),
- b->loc->line_number);
- }
- else
- /* This is not ideal, but each location may have a
- different file name, and this at least reflects the
- real situation somewhat. */
- gdb_printf (": %s.",
- event_location_to_string (b->location.get ()));
- }
- if (b->loc->next)
- {
- struct bp_location *loc = b->loc;
- int n = 0;
- for (; loc; loc = loc->next)
- ++n;
- gdb_printf (" (%d locations)", n);
- }
- }
- }
- /* See breakpoint.h. */
- bp_location_range breakpoint::locations ()
- {
- return bp_location_range (this->loc);
- }
- static struct bp_location *
- base_breakpoint_allocate_location (struct breakpoint *self)
- {
- return new bp_location (self);
- }
- static void
- base_breakpoint_re_set (struct breakpoint *b)
- {
- /* Nothing to re-set. */
- }
- #define internal_error_pure_virtual_called() \
- gdb_assert_not_reached ("pure virtual function called")
- static int
- base_breakpoint_insert_location (struct bp_location *bl)
- {
- internal_error_pure_virtual_called ();
- }
- static int
- base_breakpoint_remove_location (struct bp_location *bl,
- enum remove_bp_reason reason)
- {
- internal_error_pure_virtual_called ();
- }
- static int
- base_breakpoint_breakpoint_hit (const struct bp_location *bl,
- const address_space *aspace,
- CORE_ADDR bp_addr,
- const target_waitstatus &ws)
- {
- internal_error_pure_virtual_called ();
- }
- static void
- base_breakpoint_check_status (bpstat *bs)
- {
- /* Always stop. */
- }
- /* A "works_in_software_mode" breakpoint_ops method that just internal
- errors. */
- static int
- base_breakpoint_works_in_software_mode (const struct breakpoint *b)
- {
- internal_error_pure_virtual_called ();
- }
- /* A "resources_needed" breakpoint_ops method that just internal
- errors. */
- static int
- base_breakpoint_resources_needed (const struct bp_location *bl)
- {
- internal_error_pure_virtual_called ();
- }
- static enum print_stop_action
- base_breakpoint_print_it (bpstat *bs)
- {
- internal_error_pure_virtual_called ();
- }
- static void
- base_breakpoint_print_one_detail (const struct breakpoint *self,
- struct ui_out *uiout)
- {
- /* nothing */
- }
- static void
- base_breakpoint_print_mention (struct breakpoint *b)
- {
- internal_error_pure_virtual_called ();
- }
- static void
- base_breakpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
- {
- internal_error_pure_virtual_called ();
- }
- static void
- base_breakpoint_create_sals_from_location
- (struct event_location *location,
- struct linespec_result *canonical,
- enum bptype type_wanted)
- {
- internal_error_pure_virtual_called ();
- }
- static void
- base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch,
- struct linespec_result *c,
- gdb::unique_xmalloc_ptr<char> cond_string,
- gdb::unique_xmalloc_ptr<char> extra_string,
- enum bptype type_wanted,
- enum bpdisp disposition,
- int thread,
- int task, int ignore_count,
- const struct breakpoint_ops *o,
- int from_tty, int enabled,
- int internal, unsigned flags)
- {
- internal_error_pure_virtual_called ();
- }
- static std::vector<symtab_and_line>
- base_breakpoint_decode_location (struct breakpoint *b,
- struct event_location *location,
- struct program_space *search_pspace)
- {
- internal_error_pure_virtual_called ();
- }
- /* The default 'explains_signal' method. */
- static int
- base_breakpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
- {
- return 1;
- }
- /* The default "after_condition_true" method. */
- static void
- base_breakpoint_after_condition_true (struct bpstat *bs)
- {
- /* Nothing to do. */
- }
- struct breakpoint_ops base_breakpoint_ops =
- {
- base_breakpoint_allocate_location,
- base_breakpoint_re_set,
- base_breakpoint_insert_location,
- base_breakpoint_remove_location,
- base_breakpoint_breakpoint_hit,
- base_breakpoint_check_status,
- base_breakpoint_resources_needed,
- base_breakpoint_works_in_software_mode,
- base_breakpoint_print_it,
- NULL,
- base_breakpoint_print_one_detail,
- base_breakpoint_print_mention,
- base_breakpoint_print_recreate,
- base_breakpoint_create_sals_from_location,
- base_breakpoint_create_breakpoints_sal,
- base_breakpoint_decode_location,
- base_breakpoint_explains_signal,
- base_breakpoint_after_condition_true,
- };
- /* Default breakpoint_ops methods. */
- static void
- bkpt_re_set (struct breakpoint *b)
- {
- /* FIXME: is this still reachable? */
- if (breakpoint_event_location_empty_p (b))
- {
- /* Anything without a location can't be re-set. */
- delete_breakpoint (b);
- return;
- }
- breakpoint_re_set_default (b);
- }
- static int
- bkpt_insert_location (struct bp_location *bl)
- {
- CORE_ADDR addr = bl->target_info.reqstd_address;
- bl->target_info.kind = breakpoint_kind (bl, &addr);
- bl->target_info.placed_address = addr;
- if (bl->loc_type == bp_loc_hardware_breakpoint)
- return target_insert_hw_breakpoint (bl->gdbarch, &bl->target_info);
- else
- return target_insert_breakpoint (bl->gdbarch, &bl->target_info);
- }
- static int
- bkpt_remove_location (struct bp_location *bl, enum remove_bp_reason reason)
- {
- if (bl->loc_type == bp_loc_hardware_breakpoint)
- return target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info);
- else
- return target_remove_breakpoint (bl->gdbarch, &bl->target_info, reason);
- }
- static int
- bkpt_breakpoint_hit (const struct bp_location *bl,
- const address_space *aspace, CORE_ADDR bp_addr,
- const target_waitstatus &ws)
- {
- if (ws.kind () != TARGET_WAITKIND_STOPPED
- || ws.sig () != GDB_SIGNAL_TRAP)
- return 0;
- if (!breakpoint_address_match (bl->pspace->aspace, bl->address,
- aspace, bp_addr))
- return 0;
- if (overlay_debugging /* unmapped overlay section */
- && section_is_overlay (bl->section)
- && !section_is_mapped (bl->section))
- return 0;
- return 1;
- }
- static int
- dprintf_breakpoint_hit (const struct bp_location *bl,
- const address_space *aspace, CORE_ADDR bp_addr,
- const target_waitstatus &ws)
- {
- if (dprintf_style == dprintf_style_agent
- && target_can_run_breakpoint_commands ())
- {
- /* An agent-style dprintf never causes a stop. If we see a trap
- for this address it must be for a breakpoint that happens to
- be set at the same address. */
- return 0;
- }
- return bkpt_breakpoint_hit (bl, aspace, bp_addr, ws);
- }
- static int
- bkpt_resources_needed (const struct bp_location *bl)
- {
- gdb_assert (bl->owner->type == bp_hardware_breakpoint);
- return 1;
- }
- static enum print_stop_action
- bkpt_print_it (bpstat *bs)
- {
- struct breakpoint *b;
- const struct bp_location *bl;
- int bp_temp;
- struct ui_out *uiout = current_uiout;
- gdb_assert (bs->bp_location_at != NULL);
- bl = bs->bp_location_at.get ();
- b = bs->breakpoint_at;
- bp_temp = b->disposition == disp_del;
- if (bl->address != bl->requested_address)
- breakpoint_adjustment_warning (bl->requested_address,
- bl->address,
- b->number, 1);
- annotate_breakpoint (b->number);
- maybe_print_thread_hit_breakpoint (uiout);
- if (uiout->is_mi_like_p ())
- {
- uiout->field_string ("reason",
- async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
- uiout->field_string ("disp", bpdisp_text (b->disposition));
- }
- if (bp_temp)
- uiout->message ("Temporary breakpoint %pF, ",
- signed_field ("bkptno", b->number));
- else
- uiout->message ("Breakpoint %pF, ",
- signed_field ("bkptno", b->number));
- return PRINT_SRC_AND_LOC;
- }
- static void
- bkpt_print_mention (struct breakpoint *b)
- {
- if (current_uiout->is_mi_like_p ())
- return;
- switch (b->type)
- {
- case bp_breakpoint:
- case bp_gnu_ifunc_resolver:
- if (b->disposition == disp_del)
- gdb_printf (_("Temporary breakpoint"));
- else
- gdb_printf (_("Breakpoint"));
- gdb_printf (_(" %d"), b->number);
- if (b->type == bp_gnu_ifunc_resolver)
- gdb_printf (_(" at gnu-indirect-function resolver"));
- break;
- case bp_hardware_breakpoint:
- gdb_printf (_("Hardware assisted breakpoint %d"), b->number);
- break;
- case bp_dprintf:
- gdb_printf (_("Dprintf %d"), b->number);
- break;
- }
- say_where (b);
- }
- static void
- bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp)
- {
- if (tp->type == bp_breakpoint && tp->disposition == disp_del)
- gdb_printf (fp, "tbreak");
- else if (tp->type == bp_breakpoint)
- gdb_printf (fp, "break");
- else if (tp->type == bp_hardware_breakpoint
- && tp->disposition == disp_del)
- gdb_printf (fp, "thbreak");
- else if (tp->type == bp_hardware_breakpoint)
- gdb_printf (fp, "hbreak");
- else
- internal_error (__FILE__, __LINE__,
- _("unhandled breakpoint type %d"), (int) tp->type);
- gdb_printf (fp, " %s",
- event_location_to_string (tp->location.get ()));
- /* Print out extra_string if this breakpoint is pending. It might
- contain, for example, conditions that were set by the user. */
- if (tp->loc == NULL && tp->extra_string != NULL)
- gdb_printf (fp, " %s", tp->extra_string.get ());
- print_recreate_thread (tp, fp);
- }
- static void
- bkpt_create_sals_from_location (struct event_location *location,
- struct linespec_result *canonical,
- enum bptype type_wanted)
- {
- create_sals_from_location_default (location, canonical, type_wanted);
- }
- static void
- bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
- struct linespec_result *canonical,
- gdb::unique_xmalloc_ptr<char> cond_string,
- gdb::unique_xmalloc_ptr<char> extra_string,
- enum bptype type_wanted,
- enum bpdisp disposition,
- int thread,
- int task, int ignore_count,
- const struct breakpoint_ops *ops,
- int from_tty, int enabled,
- int internal, unsigned flags)
- {
- create_breakpoints_sal_default (gdbarch, canonical,
- std::move (cond_string),
- std::move (extra_string),
- type_wanted,
- disposition, thread, task,
- ignore_count, ops, from_tty,
- enabled, internal, flags);
- }
- static std::vector<symtab_and_line>
- bkpt_decode_location (struct breakpoint *b,
- struct event_location *location,
- struct program_space *search_pspace)
- {
- return decode_location_default (b, location, search_pspace);
- }
- /* Virtual table for internal breakpoints. */
- static void
- internal_bkpt_re_set (struct breakpoint *b)
- {
- switch (b->type)
- {
- /* Delete overlay event and longjmp master breakpoints; they
- will be reset later by breakpoint_re_set. */
- case bp_overlay_event:
- case bp_longjmp_master:
- case bp_std_terminate_master:
- case bp_exception_master:
- delete_breakpoint (b);
- break;
- /* This breakpoint is special, it's set up when the inferior
- starts and we really don't want to touch it. */
- case bp_shlib_event:
- /* Like bp_shlib_event, this breakpoint type is special. Once
- it is set up, we do not want to touch it. */
- case bp_thread_event:
- break;
- }
- }
- static void
- internal_bkpt_check_status (bpstat *bs)
- {
- if (bs->breakpoint_at->type == bp_shlib_event)
- {
- /* If requested, stop when the dynamic linker notifies GDB of
- events. This allows the user to get control and place
- breakpoints in initializer routines for dynamically loaded
- objects (among other things). */
- bs->stop = stop_on_solib_events;
- bs->print = stop_on_solib_events;
- }
- else
- bs->stop = 0;
- }
- static enum print_stop_action
- internal_bkpt_print_it (bpstat *bs)
- {
- struct breakpoint *b;
- b = bs->breakpoint_at;
- switch (b->type)
- {
- case bp_shlib_event:
- /* Did we stop because the user set the stop_on_solib_events
- variable? (If so, we report this as a generic, "Stopped due
- to shlib event" message.) */
- print_solib_event (0);
- break;
- case bp_thread_event:
- /* Not sure how we will get here.
- GDB should not stop for these breakpoints. */
- gdb_printf (_("Thread Event Breakpoint: gdb should not stop!\n"));
- break;
- case bp_overlay_event:
- /* By analogy with the thread event, GDB should not stop for these. */
- gdb_printf (_("Overlay Event Breakpoint: gdb should not stop!\n"));
- break;
- case bp_longjmp_master:
- /* These should never be enabled. */
- gdb_printf (_("Longjmp Master Breakpoint: gdb should not stop!\n"));
- break;
- case bp_std_terminate_master:
- /* These should never be enabled. */
- gdb_printf (_("std::terminate Master Breakpoint: "
- "gdb should not stop!\n"));
- break;
- case bp_exception_master:
- /* These should never be enabled. */
- gdb_printf (_("Exception Master Breakpoint: "
- "gdb should not stop!\n"));
- break;
- }
- return PRINT_NOTHING;
- }
- static void
- internal_bkpt_print_mention (struct breakpoint *b)
- {
- /* Nothing to mention. These breakpoints are internal. */
- }
- /* Virtual table for momentary breakpoints */
- static void
- momentary_bkpt_re_set (struct breakpoint *b)
- {
- /* Keep temporary breakpoints, which can be encountered when we step
- over a dlopen call and solib_add is resetting the breakpoints.
- Otherwise these should have been blown away via the cleanup chain
- or by breakpoint_init_inferior when we rerun the executable. */
- }
- static void
- momentary_bkpt_check_status (bpstat *bs)
- {
- /* Nothing. The point of these breakpoints is causing a stop. */
- }
- static enum print_stop_action
- momentary_bkpt_print_it (bpstat *bs)
- {
- return PRINT_UNKNOWN;
- }
- static void
- momentary_bkpt_print_mention (struct breakpoint *b)
- {
- /* Nothing to mention. These breakpoints are internal. */
- }
- /* Ensure INITIATING_FRAME is cleared when no such breakpoint exists.
- It gets cleared already on the removal of the first one of such placed
- breakpoints. This is OK as they get all removed altogether. */
- longjmp_breakpoint::~longjmp_breakpoint ()
- {
- thread_info *tp = find_thread_global_id (this->thread);
- if (tp != NULL)
- tp->initiating_frame = null_frame_id;
- }
- /* Specific methods for probe breakpoints. */
- static int
- bkpt_probe_insert_location (struct bp_location *bl)
- {
- int v = bkpt_insert_location (bl);
- if (v == 0)
- {
- /* The insertion was successful, now let's set the probe's semaphore
- if needed. */
- bl->probe.prob->set_semaphore (bl->probe.objfile, bl->gdbarch);
- }
- return v;
- }
- static int
- bkpt_probe_remove_location (struct bp_location *bl,
- enum remove_bp_reason reason)
- {
- /* Let's clear the semaphore before removing the location. */
- bl->probe.prob->clear_semaphore (bl->probe.objfile, bl->gdbarch);
- return bkpt_remove_location (bl, reason);
- }
- static void
- bkpt_probe_create_sals_from_location (struct event_location *location,
- struct linespec_result *canonical,
- enum bptype type_wanted)
- {
- struct linespec_sals lsal;
- lsal.sals = parse_probes (location, NULL, canonical);
- lsal.canonical
- = xstrdup (event_location_to_string (canonical->location.get ()));
- canonical->lsals.push_back (std::move (lsal));
- }
- static std::vector<symtab_and_line>
- bkpt_probe_decode_location (struct breakpoint *b,
- struct event_location *location,
- struct program_space *search_pspace)
- {
- std::vector<symtab_and_line> sals = parse_probes (location, search_pspace, NULL);
- if (sals.empty ())
- error (_("probe not found"));
- return sals;
- }
- /* The breakpoint_ops structure to be used in tracepoints. */
- static void
- tracepoint_re_set (struct breakpoint *b)
- {
- breakpoint_re_set_default (b);
- }
- static int
- tracepoint_breakpoint_hit (const struct bp_location *bl,
- const address_space *aspace, CORE_ADDR bp_addr,
- const target_waitstatus &ws)
- {
- /* By definition, the inferior does not report stops at
- tracepoints. */
- return 0;
- }
- static void
- tracepoint_print_one_detail (const struct breakpoint *self,
- struct ui_out *uiout)
- {
- struct tracepoint *tp = (struct tracepoint *) self;
- if (!tp->static_trace_marker_id.empty ())
- {
- gdb_assert (self->type == bp_static_tracepoint);
- uiout->message ("\tmarker id is %pF\n",
- string_field ("static-tracepoint-marker-string-id",
- tp->static_trace_marker_id.c_str ()));
- }
- }
- static void
- tracepoint_print_mention (struct breakpoint *b)
- {
- if (current_uiout->is_mi_like_p ())
- return;
- switch (b->type)
- {
- case bp_tracepoint:
- gdb_printf (_("Tracepoint"));
- gdb_printf (_(" %d"), b->number);
- break;
- case bp_fast_tracepoint:
- gdb_printf (_("Fast tracepoint"));
- gdb_printf (_(" %d"), b->number);
- break;
- case bp_static_tracepoint:
- gdb_printf (_("Static tracepoint"));
- gdb_printf (_(" %d"), b->number);
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("unhandled tracepoint type %d"), (int) b->type);
- }
- say_where (b);
- }
- static void
- tracepoint_print_recreate (struct breakpoint *self, struct ui_file *fp)
- {
- struct tracepoint *tp = (struct tracepoint *) self;
- if (self->type == bp_fast_tracepoint)
- gdb_printf (fp, "ftrace");
- else if (self->type == bp_static_tracepoint)
- gdb_printf (fp, "strace");
- else if (self->type == bp_tracepoint)
- gdb_printf (fp, "trace");
- else
- internal_error (__FILE__, __LINE__,
- _("unhandled tracepoint type %d"), (int) self->type);
- gdb_printf (fp, " %s",
- event_location_to_string (self->location.get ()));
- print_recreate_thread (self, fp);
- if (tp->pass_count)
- gdb_printf (fp, " passcount %d\n", tp->pass_count);
- }
- static void
- tracepoint_create_sals_from_location (struct event_location *location,
- struct linespec_result *canonical,
- enum bptype type_wanted)
- {
- create_sals_from_location_default (location, canonical, type_wanted);
- }
- static void
- tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
- struct linespec_result *canonical,
- gdb::unique_xmalloc_ptr<char> cond_string,
- gdb::unique_xmalloc_ptr<char> extra_string,
- enum bptype type_wanted,
- enum bpdisp disposition,
- int thread,
- int task, int ignore_count,
- const struct breakpoint_ops *ops,
- int from_tty, int enabled,
- int internal, unsigned flags)
- {
- create_breakpoints_sal_default (gdbarch, canonical,
- std::move (cond_string),
- std::move (extra_string),
- type_wanted,
- disposition, thread, task,
- ignore_count, ops, from_tty,
- enabled, internal, flags);
- }
- static std::vector<symtab_and_line>
- tracepoint_decode_location (struct breakpoint *b,
- struct event_location *location,
- struct program_space *search_pspace)
- {
- return decode_location_default (b, location, search_pspace);
- }
- struct breakpoint_ops tracepoint_breakpoint_ops;
- /* Virtual table for tracepoints on static probes. */
- static void
- tracepoint_probe_create_sals_from_location
- (struct event_location *location,
- struct linespec_result *canonical,
- enum bptype type_wanted)
- {
- /* We use the same method for breakpoint on probes. */
- bkpt_probe_create_sals_from_location (location, canonical, type_wanted);
- }
- static std::vector<symtab_and_line>
- tracepoint_probe_decode_location (struct breakpoint *b,
- struct event_location *location,
- struct program_space *search_pspace)
- {
- /* We use the same method for breakpoint on probes. */
- return bkpt_probe_decode_location (b, location, search_pspace);
- }
- /* Dprintf breakpoint_ops methods. */
- static void
- dprintf_re_set (struct breakpoint *b)
- {
- breakpoint_re_set_default (b);
- /* extra_string should never be non-NULL for dprintf. */
- gdb_assert (b->extra_string != NULL);
- /* 1 - connect to target 1, that can run breakpoint commands.
- 2 - create a dprintf, which resolves fine.
- 3 - disconnect from target 1
- 4 - connect to target 2, that can NOT run breakpoint commands.
- After steps #3/#4, you'll want the dprintf command list to
- be updated, because target 1 and 2 may well return different
- answers for target_can_run_breakpoint_commands().
- Given absence of finer grained resetting, we get to do
- it all the time. */
- if (b->extra_string != NULL)
- update_dprintf_command_list (b);
- }
- /* Implement the "print_recreate" breakpoint_ops method for dprintf. */
- static void
- dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp)
- {
- gdb_printf (fp, "dprintf %s,%s",
- event_location_to_string (tp->location.get ()),
- tp->extra_string.get ());
- print_recreate_thread (tp, fp);
- }
- /* Implement the "after_condition_true" breakpoint_ops method for
- dprintf.
- dprintf's are implemented with regular commands in their command
- list, but we run the commands here instead of before presenting the
- stop to the user, as dprintf's don't actually cause a stop. This
- also makes it so that the commands of multiple dprintfs at the same
- address are all handled. */
- static void
- dprintf_after_condition_true (struct bpstat *bs)
- {
- /* dprintf's never cause a stop. This wasn't set in the
- check_status hook instead because that would make the dprintf's
- condition not be evaluated. */
- bs->stop = 0;
- /* Run the command list here. Take ownership of it instead of
- copying. We never want these commands to run later in
- bpstat_do_actions, if a breakpoint that causes a stop happens to
- be set at same address as this dprintf, or even if running the
- commands here throws. */
- counted_command_line cmds = std::move (bs->commands);
- gdb_assert (cmds != nullptr);
- execute_control_commands (cmds.get (), 0);
- }
- /* The breakpoint_ops structure to be used on static tracepoints with
- markers (`-m'). */
- static void
- strace_marker_create_sals_from_location (struct event_location *location,
- struct linespec_result *canonical,
- enum bptype type_wanted)
- {
- struct linespec_sals lsal;
- const char *arg_start, *arg;
- arg = arg_start = get_linespec_location (location)->spec_string;
- lsal.sals = decode_static_tracepoint_spec (&arg);
- std::string str (arg_start, arg - arg_start);
- const char *ptr = str.c_str ();
- canonical->location
- = new_linespec_location (&ptr, symbol_name_match_type::FULL);
- lsal.canonical
- = xstrdup (event_location_to_string (canonical->location.get ()));
- canonical->lsals.push_back (std::move (lsal));
- }
- static void
- strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
- struct linespec_result *canonical,
- gdb::unique_xmalloc_ptr<char> cond_string,
- gdb::unique_xmalloc_ptr<char> extra_string,
- enum bptype type_wanted,
- enum bpdisp disposition,
- int thread,
- int task, int ignore_count,
- const struct breakpoint_ops *ops,
- int from_tty, int enabled,
- int internal, unsigned flags)
- {
- const linespec_sals &lsal = canonical->lsals[0];
- /* If the user is creating a static tracepoint by marker id
- (strace -m MARKER_ID), then store the sals index, so that
- breakpoint_re_set can try to match up which of the newly
- found markers corresponds to this one, and, don't try to
- expand multiple locations for each sal, given than SALS
- already should contain all sals for MARKER_ID. */
- for (size_t i = 0; i < lsal.sals.size (); i++)
- {
- event_location_up location
- = copy_event_location (canonical->location.get ());
- std::unique_ptr<tracepoint> tp (new tracepoint ());
- init_breakpoint_sal (tp.get (), gdbarch, lsal.sals[i],
- std::move (location), NULL,
- std::move (cond_string),
- std::move (extra_string),
- type_wanted, disposition,
- thread, task, ignore_count, ops,
- from_tty, enabled, internal, flags,
- canonical->special_display);
- /* Given that its possible to have multiple markers with
- the same string id, if the user is creating a static
- tracepoint by marker id ("strace -m MARKER_ID"), then
- store the sals index, so that breakpoint_re_set can
- try to match up which of the newly found markers
- corresponds to this one */
- tp->static_trace_marker_id_idx = i;
- install_breakpoint (internal, std::move (tp), 0);
- }
- }
- static std::vector<symtab_and_line>
- strace_marker_decode_location (struct breakpoint *b,
- struct event_location *location,
- struct program_space *search_pspace)
- {
- struct tracepoint *tp = (struct tracepoint *) b;
- const char *s = get_linespec_location (location)->spec_string;
- std::vector<symtab_and_line> sals = decode_static_tracepoint_spec (&s);
- if (sals.size () > tp->static_trace_marker_id_idx)
- {
- sals[0] = sals[tp->static_trace_marker_id_idx];
- sals.resize (1);
- return sals;
- }
- else
- error (_("marker %s not found"), tp->static_trace_marker_id.c_str ());
- }
- static struct breakpoint_ops strace_marker_breakpoint_ops;
- static int
- strace_marker_p (struct breakpoint *b)
- {
- return b->ops == &strace_marker_breakpoint_ops;
- }
- /* Delete a breakpoint and clean up all traces of it in the data
- structures. */
- void
- delete_breakpoint (struct breakpoint *bpt)
- {
- gdb_assert (bpt != NULL);
- /* Has this bp already been deleted? This can happen because
- multiple lists can hold pointers to bp's. bpstat lists are
- especial culprits.
- One example of this happening is a watchpoint's scope bp. When
- the scope bp triggers, we notice that the watchpoint is out of
- scope, and delete it. We also delete its scope bp. But the
- scope bp is marked "auto-deleting", and is already on a bpstat.
- That bpstat is then checked for auto-deleting bp's, which are
- deleted.
- A real solution to this problem might involve reference counts in
- bp's, and/or giving them pointers back to their referencing
- bpstat's, and teaching delete_breakpoint to only free a bp's
- storage when no more references were extent. A cheaper bandaid
- was chosen. */
- if (bpt->type == bp_none)
- return;
- /* At least avoid this stale reference until the reference counting
- of breakpoints gets resolved. */
- if (bpt->related_breakpoint != bpt)
- {
- struct breakpoint *related;
- struct watchpoint *w;
- if (bpt->type == bp_watchpoint_scope)
- w = (struct watchpoint *) bpt->related_breakpoint;
- else if (bpt->related_breakpoint->type == bp_watchpoint_scope)
- w = (struct watchpoint *) bpt;
- else
- w = NULL;
- if (w != NULL)
- watchpoint_del_at_next_stop (w);
- /* Unlink bpt from the bpt->related_breakpoint ring. */
- for (related = bpt; related->related_breakpoint != bpt;
- related = related->related_breakpoint);
- related->related_breakpoint = bpt->related_breakpoint;
- bpt->related_breakpoint = bpt;
- }
- /* watch_command_1 creates a watchpoint but only sets its number if
- update_watchpoint succeeds in creating its bp_locations. If there's
- a problem in that process, we'll be asked to delete the half-created
- watchpoint. In that case, don't announce the deletion. */
- if (bpt->number)
- gdb::observers::breakpoint_deleted.notify (bpt);
- if (breakpoint_chain == bpt)
- breakpoint_chain = bpt->next;
- for (breakpoint *b : all_breakpoints ())
- if (b->next == bpt)
- {
- b->next = bpt->next;
- break;
- }
- /* Be sure no bpstat's are pointing at the breakpoint after it's
- been freed. */
- /* FIXME, how can we find all bpstat's? We just check stop_bpstat
- in all threads for now. Note that we cannot just remove bpstats
- pointing at bpt from the stop_bpstat list entirely, as breakpoint
- commands are associated with the bpstat; if we remove it here,
- then the later call to bpstat_do_actions (&stop_bpstat); in
- event-top.c won't do anything, and temporary breakpoints with
- commands won't work. */
- iterate_over_threads (bpstat_remove_breakpoint_callback, bpt);
- /* Now that breakpoint is removed from breakpoint list, update the
- global location list. This will remove locations that used to
- belong to this breakpoint. Do this before freeing the breakpoint
- itself, since remove_breakpoint looks at location's owner. It
- might be better design to have location completely
- self-contained, but it's not the case now. */
- update_global_location_list (UGLL_DONT_INSERT);
- /* On the chance that someone will soon try again to delete this
- same bp, we mark it as deleted before freeing its storage. */
- bpt->type = bp_none;
- delete bpt;
- }
- /* Iterator function to call a user-provided callback function once
- for each of B and its related breakpoints. */
- static void
- iterate_over_related_breakpoints (struct breakpoint *b,
- gdb::function_view<void (breakpoint *)> function)
- {
- struct breakpoint *related;
- related = b;
- do
- {
- struct breakpoint *next;
- /* FUNCTION may delete RELATED. */
- next = related->related_breakpoint;
- if (next == related)
- {
- /* RELATED is the last ring entry. */
- function (related);
- /* FUNCTION may have deleted it, so we'd never reach back to
- B. There's nothing left to do anyway, so just break
- out. */
- break;
- }
- else
- function (related);
- related = next;
- }
- while (related != b);
- }
- static void
- delete_command (const char *arg, int from_tty)
- {
- dont_repeat ();
- if (arg == 0)
- {
- int breaks_to_delete = 0;
- /* Delete all breakpoints if no argument. Do not delete
- internal breakpoints, these have to be deleted with an
- explicit breakpoint number argument. */
- for (breakpoint *b : all_breakpoints ())
- if (user_breakpoint_p (b))
- {
- breaks_to_delete = 1;
- break;
- }
- /* Ask user only if there are some breakpoints to delete. */
- if (!from_tty
- || (breaks_to_delete && query (_("Delete all breakpoints? "))))
- for (breakpoint *b : all_breakpoints_safe ())
- if (user_breakpoint_p (b))
- delete_breakpoint (b);
- }
- else
- map_breakpoint_numbers
- (arg, [&] (breakpoint *br)
- {
- iterate_over_related_breakpoints (br, delete_breakpoint);
- });
- }
- /* Return true if all locations of B bound to PSPACE are pending. If
- PSPACE is NULL, all locations of all program spaces are
- considered. */
- static int
- all_locations_are_pending (struct breakpoint *b, struct program_space *pspace)
- {
- for (bp_location *loc : b->locations ())
- if ((pspace == NULL
- || loc->pspace == pspace)
- && !loc->shlib_disabled
- && !loc->pspace->executing_startup)
- return 0;
- return 1;
- }
- /* Subroutine of update_breakpoint_locations to simplify it.
- Return non-zero if multiple fns in list LOC have the same name.
- Null names are ignored. */
- static int
- ambiguous_names_p (struct bp_location *loc)
- {
- struct bp_location *l;
- htab_up htab (htab_create_alloc (13, htab_hash_string, htab_eq_string, NULL,
- xcalloc, xfree));
- for (l = loc; l != NULL; l = l->next)
- {
- const char **slot;
- const char *name = l->function_name.get ();
- /* Allow for some names to be NULL, ignore them. */
- if (name == NULL)
- continue;
- slot = (const char **) htab_find_slot (htab.get (), (const void *) name,
- INSERT);
- /* NOTE: We can assume slot != NULL here because xcalloc never
- returns NULL. */
- if (*slot != NULL)
- return 1;
- *slot = name;
- }
- return 0;
- }
- /* When symbols change, it probably means the sources changed as well,
- and it might mean the static tracepoint markers are no longer at
- the same address or line numbers they used to be at last we
- checked. Losing your static tracepoints whenever you rebuild is
- undesirable. This function tries to resync/rematch gdb static
- tracepoints with the markers on the target, for static tracepoints
- that have not been set by marker id. Static tracepoint that have
- been set by marker id are reset by marker id in breakpoint_re_set.
- The heuristic is:
- 1) For a tracepoint set at a specific address, look for a marker at
- the old PC. If one is found there, assume to be the same marker.
- If the name / string id of the marker found is different from the
- previous known name, assume that means the user renamed the marker
- in the sources, and output a warning.
- 2) For a tracepoint set at a given line number, look for a marker
- at the new address of the old line number. If one is found there,
- assume to be the same marker. If the name / string id of the
- marker found is different from the previous known name, assume that
- means the user renamed the marker in the sources, and output a
- warning.
- 3) If a marker is no longer found at the same address or line, it
- may mean the marker no longer exists. But it may also just mean
- the code changed a bit. Maybe the user added a few lines of code
- that made the marker move up or down (in line number terms). Ask
- the target for info about the marker with the string id as we knew
- it. If found, update line number and address in the matching
- static tracepoint. This will get confused if there's more than one
- marker with the same ID (possible in UST, although unadvised
- precisely because it confuses tools). */
- static struct symtab_and_line
- update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
- {
- struct tracepoint *tp = (struct tracepoint *) b;
- struct static_tracepoint_marker marker;
- CORE_ADDR pc;
- pc = sal.pc;
- if (sal.line)
- find_line_pc (sal.symtab, sal.line, &pc);
- if (target_static_tracepoint_marker_at (pc, &marker))
- {
- if (tp->static_trace_marker_id != marker.str_id)
- warning (_("static tracepoint %d changed probed marker from %s to %s"),
- b->number, tp->static_trace_marker_id.c_str (),
- marker.str_id.c_str ());
- tp->static_trace_marker_id = std::move (marker.str_id);
- return sal;
- }
- /* Old marker wasn't found on target at lineno. Try looking it up
- by string ID. */
- if (!sal.explicit_pc
- && sal.line != 0
- && sal.symtab != NULL
- && !tp->static_trace_marker_id.empty ())
- {
- std::vector<static_tracepoint_marker> markers
- = target_static_tracepoint_markers_by_strid
- (tp->static_trace_marker_id.c_str ());
- if (!markers.empty ())
- {
- struct symbol *sym;
- struct static_tracepoint_marker *tpmarker;
- struct ui_out *uiout = current_uiout;
- struct explicit_location explicit_loc;
- tpmarker = &markers[0];
- tp->static_trace_marker_id = std::move (tpmarker->str_id);
- warning (_("marker for static tracepoint %d (%s) not "
- "found at previous line number"),
- b->number, tp->static_trace_marker_id.c_str ());
- symtab_and_line sal2 = find_pc_line (tpmarker->address, 0);
- sym = find_pc_sect_function (tpmarker->address, NULL);
- uiout->text ("Now in ");
- if (sym)
- {
- uiout->field_string ("func", sym->print_name (),
- function_name_style.style ());
- uiout->text (" at ");
- }
- uiout->field_string ("file",
- symtab_to_filename_for_display (sal2.symtab),
- file_name_style.style ());
- uiout->text (":");
- if (uiout->is_mi_like_p ())
- {
- const char *fullname = symtab_to_fullname (sal2.symtab);
- uiout->field_string ("fullname", fullname);
- }
- uiout->field_signed ("line", sal2.line);
- uiout->text ("\n");
- b->loc->line_number = sal2.line;
- b->loc->symtab = sym != NULL ? sal2.symtab : NULL;
- b->location.reset (NULL);
- initialize_explicit_location (&explicit_loc);
- explicit_loc.source_filename
- = ASTRDUP (symtab_to_filename_for_display (sal2.symtab));
- explicit_loc.line_offset.offset = b->loc->line_number;
- explicit_loc.line_offset.sign = LINE_OFFSET_NONE;
- b->location = new_explicit_location (&explicit_loc);
- /* Might be nice to check if function changed, and warn if
- so. */
- }
- }
- return sal;
- }
- /* Returns 1 iff locations A and B are sufficiently same that
- we don't need to report breakpoint as changed. */
- static int
- locations_are_equal (struct bp_location *a, struct bp_location *b)
- {
- while (a && b)
- {
- if (a->address != b->address)
- return 0;
- if (a->shlib_disabled != b->shlib_disabled)
- return 0;
- if (a->enabled != b->enabled)
- return 0;
- if (a->disabled_by_cond != b->disabled_by_cond)
- return 0;
- a = a->next;
- b = b->next;
- }
- if ((a == NULL) != (b == NULL))
- return 0;
- return 1;
- }
- /* Split all locations of B that are bound to PSPACE out of B's
- location list to a separate list and return that list's head. If
- PSPACE is NULL, hoist out all locations of B. */
- static struct bp_location *
- hoist_existing_locations (struct breakpoint *b, struct program_space *pspace)
- {
- struct bp_location head;
- struct bp_location *i = b->loc;
- struct bp_location **i_link = &b->loc;
- struct bp_location *hoisted = &head;
- if (pspace == NULL)
- {
- i = b->loc;
- b->loc = NULL;
- return i;
- }
- head.next = NULL;
- while (i != NULL)
- {
- if (i->pspace == pspace)
- {
- *i_link = i->next;
- i->next = NULL;
- hoisted->next = i;
- hoisted = i;
- }
- else
- i_link = &i->next;
- i = *i_link;
- }
- return head.next;
- }
- /* Create new breakpoint locations for B (a hardware or software
- breakpoint) based on SALS and SALS_END. If SALS_END.NELTS is not
- zero, then B is a ranged breakpoint. Only recreates locations for
- FILTER_PSPACE. Locations of other program spaces are left
- untouched. */
- void
- update_breakpoint_locations (struct breakpoint *b,
- struct program_space *filter_pspace,
- gdb::array_view<const symtab_and_line> sals,
- gdb::array_view<const symtab_and_line> sals_end)
- {
- struct bp_location *existing_locations;
- if (!sals_end.empty () && (sals.size () != 1 || sals_end.size () != 1))
- {
- /* Ranged breakpoints have only one start location and one end
- location. */
- b->enable_state = bp_disabled;
- gdb_printf (gdb_stderr,
- _("Could not reset ranged breakpoint %d: "
- "multiple locations found\n"),
- b->number);
- return;
- }
- /* If there's no new locations, and all existing locations are
- pending, don't do anything. This optimizes the common case where
- all locations are in the same shared library, that was unloaded.
- We'd like to retain the location, so that when the library is
- loaded again, we don't loose the enabled/disabled status of the
- individual locations. */
- if (all_locations_are_pending (b, filter_pspace) && sals.empty ())
- return;
- existing_locations = hoist_existing_locations (b, filter_pspace);
- for (const auto &sal : sals)
- {
- struct bp_location *new_loc;
- switch_to_program_space_and_thread (sal.pspace);
- new_loc = add_location_to_breakpoint (b, &sal);
- /* Reparse conditions, they might contain references to the
- old symtab. */
- if (b->cond_string != NULL)
- {
- const char *s;
- s = b->cond_string.get ();
- try
- {
- new_loc->cond = parse_exp_1 (&s, sal.pc,
- block_for_pc (sal.pc),
- 0);
- }
- catch (const gdb_exception_error &e)
- {
- new_loc->disabled_by_cond = true;
- }
- }
- if (!sals_end.empty ())
- {
- CORE_ADDR end = find_breakpoint_range_end (sals_end[0]);
- new_loc->length = end - sals[0].pc + 1;
- }
- }
- /* If possible, carry over 'disable' status from existing
- breakpoints. */
- {
- struct bp_location *e = existing_locations;
- /* If there are multiple breakpoints with the same function name,
- e.g. for inline functions, comparing function names won't work.
- Instead compare pc addresses; this is just a heuristic as things
- may have moved, but in practice it gives the correct answer
- often enough until a better solution is found. */
- int have_ambiguous_names = ambiguous_names_p (b->loc);
- for (; e; e = e->next)
- {
- if ((!e->enabled || e->disabled_by_cond) && e->function_name)
- {
- if (have_ambiguous_names)
- {
- for (bp_location *l : b->locations ())
- {
- /* Ignore software vs hardware location type at
- this point, because with "set breakpoint
- auto-hw", after a re-set, locations that were
- hardware can end up as software, or vice versa.
- As mentioned above, this is an heuristic and in
- practice should give the correct answer often
- enough. */
- if (breakpoint_locations_match (e, l, true))
- {
- l->enabled = e->enabled;
- l->disabled_by_cond = e->disabled_by_cond;
- break;
- }
- }
- }
- else
- {
- for (bp_location *l : b->locations ())
- if (l->function_name
- && strcmp (e->function_name.get (),
- l->function_name.get ()) == 0)
- {
- l->enabled = e->enabled;
- l->disabled_by_cond = e->disabled_by_cond;
- break;
- }
- }
- }
- }
- }
- if (!locations_are_equal (existing_locations, b->loc))
- gdb::observers::breakpoint_modified.notify (b);
- }
- /* Find the SaL locations corresponding to the given LOCATION.
- On return, FOUND will be 1 if any SaL was found, zero otherwise. */
- static std::vector<symtab_and_line>
- location_to_sals (struct breakpoint *b, struct event_location *location,
- struct program_space *search_pspace, int *found)
- {
- struct gdb_exception exception;
- gdb_assert (b->ops != NULL);
- std::vector<symtab_and_line> sals;
- try
- {
- sals = b->ops->decode_location (b, location, search_pspace);
- }
- catch (gdb_exception_error &e)
- {
- int not_found_and_ok = 0;
- /* For pending breakpoints, it's expected that parsing will
- fail until the right shared library is loaded. User has
- already told to create pending breakpoints and don't need
- extra messages. If breakpoint is in bp_shlib_disabled
- state, then user already saw the message about that
- breakpoint being disabled, and don't want to see more
- errors. */
- if (e.error == NOT_FOUND_ERROR
- && (b->condition_not_parsed
- || (b->loc != NULL
- && search_pspace != NULL
- && b->loc->pspace != search_pspace)
- || (b->loc && b->loc->shlib_disabled)
- || (b->loc && b->loc->pspace->executing_startup)
- || b->enable_state == bp_disabled))
- not_found_and_ok = 1;
- if (!not_found_and_ok)
- {
- /* We surely don't want to warn about the same breakpoint
- 10 times. One solution, implemented here, is disable
- the breakpoint on error. Another solution would be to
- have separate 'warning emitted' flag. Since this
- happens only when a binary has changed, I don't know
- which approach is better. */
- b->enable_state = bp_disabled;
- throw;
- }
- exception = std::move (e);
- }
- if (exception.reason == 0 || exception.error != NOT_FOUND_ERROR)
- {
- for (auto &sal : sals)
- resolve_sal_pc (&sal);
- if (b->condition_not_parsed && b->extra_string != NULL)
- {
- gdb::unique_xmalloc_ptr<char> cond_string, extra_string;
- int thread, task;
- find_condition_and_thread_for_sals (sals, b->extra_string.get (),
- &cond_string, &thread,
- &task, &extra_string);
- gdb_assert (b->cond_string == NULL);
- if (cond_string)
- b->cond_string = std::move (cond_string);
- b->thread = thread;
- b->task = task;
- if (extra_string)
- b->extra_string = std::move (extra_string);
- b->condition_not_parsed = 0;
- }
- if (b->type == bp_static_tracepoint && !strace_marker_p (b))
- sals[0] = update_static_tracepoint (b, sals[0]);
- *found = 1;
- }
- else
- *found = 0;
- return sals;
- }
- /* The default re_set method, for typical hardware or software
- breakpoints. Reevaluate the breakpoint and recreate its
- locations. */
- static void
- breakpoint_re_set_default (struct breakpoint *b)
- {
- struct program_space *filter_pspace = current_program_space;
- std::vector<symtab_and_line> expanded, expanded_end;
- int found;
- std::vector<symtab_and_line> sals = location_to_sals (b, b->location.get (),
- filter_pspace, &found);
- if (found)
- expanded = std::move (sals);
- if (b->location_range_end != NULL)
- {
- std::vector<symtab_and_line> sals_end
- = location_to_sals (b, b->location_range_end.get (),
- filter_pspace, &found);
- if (found)
- expanded_end = std::move (sals_end);
- }
- update_breakpoint_locations (b, filter_pspace, expanded, expanded_end);
- }
- /* Default method for creating SALs from an address string. It basically
- calls parse_breakpoint_sals. Return 1 for success, zero for failure. */
- static void
- create_sals_from_location_default (struct event_location *location,
- struct linespec_result *canonical,
- enum bptype type_wanted)
- {
- parse_breakpoint_sals (location, canonical);
- }
- /* Call create_breakpoints_sal for the given arguments. This is the default
- function for the `create_breakpoints_sal' method of
- breakpoint_ops. */
- static void
- create_breakpoints_sal_default (struct gdbarch *gdbarch,
- struct linespec_result *canonical,
- gdb::unique_xmalloc_ptr<char> cond_string,
- gdb::unique_xmalloc_ptr<char> extra_string,
- enum bptype type_wanted,
- enum bpdisp disposition,
- int thread,
- int task, int ignore_count,
- const struct breakpoint_ops *ops,
- int from_tty, int enabled,
- int internal, unsigned flags)
- {
- create_breakpoints_sal (gdbarch, canonical,
- std::move (cond_string),
- std::move (extra_string),
- type_wanted, disposition,
- thread, task, ignore_count, ops, from_tty,
- enabled, internal, flags);
- }
- /* Decode the line represented by S by calling decode_line_full. This is the
- default function for the `decode_location' method of breakpoint_ops. */
- static std::vector<symtab_and_line>
- decode_location_default (struct breakpoint *b,
- struct event_location *location,
- struct program_space *search_pspace)
- {
- struct linespec_result canonical;
- decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, search_pspace,
- NULL, 0, &canonical, multiple_symbols_all,
- b->filter.get ());
- /* We should get 0 or 1 resulting SALs. */
- gdb_assert (canonical.lsals.size () < 2);
- if (!canonical.lsals.empty ())
- {
- const linespec_sals &lsal = canonical.lsals[0];
- return std::move (lsal.sals);
- }
- return {};
- }
- /* Reset a breakpoint. */
- static void
- breakpoint_re_set_one (breakpoint *b)
- {
- input_radix = b->input_radix;
- set_language (b->language);
- b->ops->re_set (b);
- }
- /* Re-set breakpoint locations for the current program space.
- Locations bound to other program spaces are left untouched. */
- void
- breakpoint_re_set (void)
- {
- {
- scoped_restore_current_language save_language;
- scoped_restore save_input_radix = make_scoped_restore (&input_radix);
- scoped_restore_current_pspace_and_thread restore_pspace_thread;
- /* breakpoint_re_set_one sets the current_language to the language
- of the breakpoint it is resetting (see prepare_re_set_context)
- before re-evaluating the breakpoint's location. This change can
- unfortunately get undone by accident if the language_mode is set
- to auto, and we either switch frames, or more likely in this context,
- we select the current frame.
- We prevent this by temporarily turning the language_mode to
- language_mode_manual. We restore it once all breakpoints
- have been reset. */
- scoped_restore save_language_mode = make_scoped_restore (&language_mode);
- language_mode = language_mode_manual;
- /* Note: we must not try to insert locations until after all
- breakpoints have been re-set. Otherwise, e.g., when re-setting
- breakpoint 1, we'd insert the locations of breakpoint 2, which
- hadn't been re-set yet, and thus may have stale locations. */
- for (breakpoint *b : all_breakpoints_safe ())
- {
- try
- {
- breakpoint_re_set_one (b);
- }
- catch (const gdb_exception &ex)
- {
- exception_fprintf (gdb_stderr, ex,
- "Error in re-setting breakpoint %d: ",
- b->number);
- }
- }
- jit_breakpoint_re_set ();
- }
- create_overlay_event_breakpoint ();
- create_longjmp_master_breakpoint ();
- create_std_terminate_master_breakpoint ();
- create_exception_master_breakpoint ();
- /* Now we can insert. */
- update_global_location_list (UGLL_MAY_INSERT);
- }
- /* Reset the thread number of this breakpoint:
- - If the breakpoint is for all threads, leave it as-is.
- - Else, reset it to the current thread for inferior_ptid. */
- void
- breakpoint_re_set_thread (struct breakpoint *b)
- {
- if (b->thread != -1)
- {
- b->thread = inferior_thread ()->global_num;
- /* We're being called after following a fork. The new fork is
- selected as current, and unless this was a vfork will have a
- different program space from the original thread. Reset that
- as well. */
- b->loc->pspace = current_program_space;
- }
- }
- /* Set ignore-count of breakpoint number BPTNUM to COUNT.
- If from_tty is nonzero, it prints a message to that effect,
- which ends with a period (no newline). */
- void
- set_ignore_count (int bptnum, int count, int from_tty)
- {
- if (count < 0)
- count = 0;
- for (breakpoint *b : all_breakpoints ())
- if (b->number == bptnum)
- {
- if (is_tracepoint (b))
- {
- if (from_tty && count != 0)
- gdb_printf (_("Ignore count ignored for tracepoint %d."),
- bptnum);
- return;
- }
- b->ignore_count = count;
- if (from_tty)
- {
- if (count == 0)
- gdb_printf (_("Will stop next time "
- "breakpoint %d is reached."),
- bptnum);
- else if (count == 1)
- gdb_printf (_("Will ignore next crossing of breakpoint %d."),
- bptnum);
- else
- gdb_printf (_("Will ignore next %d "
- "crossings of breakpoint %d."),
- count, bptnum);
- }
- gdb::observers::breakpoint_modified.notify (b);
- return;
- }
- error (_("No breakpoint number %d."), bptnum);
- }
- /* Command to set ignore-count of breakpoint N to COUNT. */
- static void
- ignore_command (const char *args, int from_tty)
- {
- const char *p = args;
- int num;
- if (p == 0)
- error_no_arg (_("a breakpoint number"));
- num = get_number (&p);
- if (num == 0)
- error (_("bad breakpoint number: '%s'"), args);
- if (*p == 0)
- error (_("Second argument (specified ignore-count) is missing."));
- set_ignore_count (num,
- longest_to_int (value_as_long (parse_and_eval (p))),
- from_tty);
- if (from_tty)
- gdb_printf ("\n");
- }
- /* Call FUNCTION on each of the breakpoints with numbers in the range
- defined by BP_NUM_RANGE (an inclusive range). */
- static void
- map_breakpoint_number_range (std::pair<int, int> bp_num_range,
- gdb::function_view<void (breakpoint *)> function)
- {
- if (bp_num_range.first == 0)
- {
- warning (_("bad breakpoint number at or near '%d'"),
- bp_num_range.first);
- }
- else
- {
- for (int i = bp_num_range.first; i <= bp_num_range.second; i++)
- {
- bool match = false;
- for (breakpoint *b : all_breakpoints_safe ())
- if (b->number == i)
- {
- match = true;
- function (b);
- break;
- }
- if (!match)
- gdb_printf (_("No breakpoint number %d.\n"), i);
- }
- }
- }
- /* Call FUNCTION on each of the breakpoints whose numbers are given in
- ARGS. */
- static void
- map_breakpoint_numbers (const char *args,
- gdb::function_view<void (breakpoint *)> function)
- {
- if (args == NULL || *args == '\0')
- error_no_arg (_("one or more breakpoint numbers"));
- number_or_range_parser parser (args);
- while (!parser.finished ())
- {
- int num = parser.get_number ();
- map_breakpoint_number_range (std::make_pair (num, num), function);
- }
- }
- /* Return the breakpoint location structure corresponding to the
- BP_NUM and LOC_NUM values. */
- static struct bp_location *
- find_location_by_number (int bp_num, int loc_num)
- {
- breakpoint *b = get_breakpoint (bp_num);
- if (!b || b->number != bp_num)
- error (_("Bad breakpoint number '%d'"), bp_num);
-
- if (loc_num == 0)
- error (_("Bad breakpoint location number '%d'"), loc_num);
- int n = 0;
- for (bp_location *loc : b->locations ())
- if (++n == loc_num)
- return loc;
- error (_("Bad breakpoint location number '%d'"), loc_num);
- }
- /* Modes of operation for extract_bp_num. */
- enum class extract_bp_kind
- {
- /* Extracting a breakpoint number. */
- bp,
- /* Extracting a location number. */
- loc,
- };
- /* Extract a breakpoint or location number (as determined by KIND)
- from the string starting at START. TRAILER is a character which
- can be found after the number. If you don't want a trailer, use
- '\0'. If END_OUT is not NULL, it is set to point after the parsed
- string. This always returns a positive integer. */
- static int
- extract_bp_num (extract_bp_kind kind, const char *start,
- int trailer, const char **end_out = NULL)
- {
- const char *end = start;
- int num = get_number_trailer (&end, trailer);
- if (num < 0)
- error (kind == extract_bp_kind::bp
- ? _("Negative breakpoint number '%.*s'")
- : _("Negative breakpoint location number '%.*s'"),
- int (end - start), start);
- if (num == 0)
- error (kind == extract_bp_kind::bp
- ? _("Bad breakpoint number '%.*s'")
- : _("Bad breakpoint location number '%.*s'"),
- int (end - start), start);
- if (end_out != NULL)
- *end_out = end;
- return num;
- }
- /* Extract a breakpoint or location range (as determined by KIND) in
- the form NUM1-NUM2 stored at &ARG[arg_offset]. Returns a std::pair
- representing the (inclusive) range. The returned pair's elements
- are always positive integers. */
- static std::pair<int, int>
- extract_bp_or_bp_range (extract_bp_kind kind,
- const std::string &arg,
- std::string::size_type arg_offset)
- {
- std::pair<int, int> range;
- const char *bp_loc = &arg[arg_offset];
- std::string::size_type dash = arg.find ('-', arg_offset);
- if (dash != std::string::npos)
- {
- /* bp_loc is a range (x-z). */
- if (arg.length () == dash + 1)
- error (kind == extract_bp_kind::bp
- ? _("Bad breakpoint number at or near: '%s'")
- : _("Bad breakpoint location number at or near: '%s'"),
- bp_loc);
- const char *end;
- const char *start_first = bp_loc;
- const char *start_second = &arg[dash + 1];
- range.first = extract_bp_num (kind, start_first, '-');
- range.second = extract_bp_num (kind, start_second, '\0', &end);
- if (range.first > range.second)
- error (kind == extract_bp_kind::bp
- ? _("Inverted breakpoint range at '%.*s'")
- : _("Inverted breakpoint location range at '%.*s'"),
- int (end - start_first), start_first);
- }
- else
- {
- /* bp_loc is a single value. */
- range.first = extract_bp_num (kind, bp_loc, '\0');
- range.second = range.first;
- }
- return range;
- }
- /* Extract the breakpoint/location range specified by ARG. Returns
- the breakpoint range in BP_NUM_RANGE, and the location range in
- BP_LOC_RANGE.
- ARG may be in any of the following forms:
- x where 'x' is a breakpoint number.
- x-y where 'x' and 'y' specify a breakpoint numbers range.
- x.y where 'x' is a breakpoint number and 'y' a location number.
- x.y-z where 'x' is a breakpoint number and 'y' and 'z' specify a
- location number range.
- */
- static void
- extract_bp_number_and_location (const std::string &arg,
- std::pair<int, int> &bp_num_range,
- std::pair<int, int> &bp_loc_range)
- {
- std::string::size_type dot = arg.find ('.');
- if (dot != std::string::npos)
- {
- /* Handle 'x.y' and 'x.y-z' cases. */
- if (arg.length () == dot + 1 || dot == 0)
- error (_("Bad breakpoint number at or near: '%s'"), arg.c_str ());
- bp_num_range.first
- = extract_bp_num (extract_bp_kind::bp, arg.c_str (), '.');
- bp_num_range.second = bp_num_range.first;
- bp_loc_range = extract_bp_or_bp_range (extract_bp_kind::loc,
- arg, dot + 1);
- }
- else
- {
- /* Handle x and x-y cases. */
- bp_num_range = extract_bp_or_bp_range (extract_bp_kind::bp, arg, 0);
- bp_loc_range.first = 0;
- bp_loc_range.second = 0;
- }
- }
- /* Enable or disable a breakpoint location BP_NUM.LOC_NUM. ENABLE
- specifies whether to enable or disable. */
- static void
- enable_disable_bp_num_loc (int bp_num, int loc_num, bool enable)
- {
- struct bp_location *loc = find_location_by_number (bp_num, loc_num);
- if (loc != NULL)
- {
- if (loc->disabled_by_cond && enable)
- error (_("Breakpoint %d's condition is invalid at location %d, "
- "cannot enable."), bp_num, loc_num);
- if (loc->enabled != enable)
- {
- loc->enabled = enable;
- mark_breakpoint_location_modified (loc);
- }
- if (target_supports_enable_disable_tracepoint ()
- && current_trace_status ()->running && loc->owner
- && is_tracepoint (loc->owner))
- target_disable_tracepoint (loc);
- }
- update_global_location_list (UGLL_DONT_INSERT);
- gdb::observers::breakpoint_modified.notify (loc->owner);
- }
- /* Enable or disable a range of breakpoint locations. BP_NUM is the
- number of the breakpoint, and BP_LOC_RANGE specifies the
- (inclusive) range of location numbers of that breakpoint to
- enable/disable. ENABLE specifies whether to enable or disable the
- location. */
- static void
- enable_disable_breakpoint_location_range (int bp_num,
- std::pair<int, int> &bp_loc_range,
- bool enable)
- {
- for (int i = bp_loc_range.first; i <= bp_loc_range.second; i++)
- enable_disable_bp_num_loc (bp_num, i, enable);
- }
- /* Set ignore-count of breakpoint number BPTNUM to COUNT.
- If from_tty is nonzero, it prints a message to that effect,
- which ends with a period (no newline). */
- void
- disable_breakpoint (struct breakpoint *bpt)
- {
- /* Never disable a watchpoint scope breakpoint; we want to
- hit them when we leave scope so we can delete both the
- watchpoint and its scope breakpoint at that time. */
- if (bpt->type == bp_watchpoint_scope)
- return;
- bpt->enable_state = bp_disabled;
- /* Mark breakpoint locations modified. */
- mark_breakpoint_modified (bpt);
- if (target_supports_enable_disable_tracepoint ()
- && current_trace_status ()->running && is_tracepoint (bpt))
- {
- for (bp_location *location : bpt->locations ())
- target_disable_tracepoint (location);
- }
- update_global_location_list (UGLL_DONT_INSERT);
- gdb::observers::breakpoint_modified.notify (bpt);
- }
- /* Enable or disable the breakpoint(s) or breakpoint location(s)
- specified in ARGS. ARGS may be in any of the formats handled by
- extract_bp_number_and_location. ENABLE specifies whether to enable
- or disable the breakpoints/locations. */
- static void
- enable_disable_command (const char *args, int from_tty, bool enable)
- {
- if (args == 0)
- {
- for (breakpoint *bpt : all_breakpoints ())
- if (user_breakpoint_p (bpt))
- {
- if (enable)
- enable_breakpoint (bpt);
- else
- disable_breakpoint (bpt);
- }
- }
- else
- {
- std::string num = extract_arg (&args);
- while (!num.empty ())
- {
- std::pair<int, int> bp_num_range, bp_loc_range;
- extract_bp_number_and_location (num, bp_num_range, bp_loc_range);
- if (bp_loc_range.first == bp_loc_range.second
- && bp_loc_range.first == 0)
- {
- /* Handle breakpoint ids with formats 'x' or 'x-z'. */
- map_breakpoint_number_range (bp_num_range,
- enable
- ? enable_breakpoint
- : disable_breakpoint);
- }
- else
- {
- /* Handle breakpoint ids with formats 'x.y' or
- 'x.y-z'. */
- enable_disable_breakpoint_location_range
- (bp_num_range.first, bp_loc_range, enable);
- }
- num = extract_arg (&args);
- }
- }
- }
- /* The disable command disables the specified breakpoints/locations
- (or all defined breakpoints) so they're no longer effective in
- stopping the inferior. ARGS may be in any of the forms defined in
- extract_bp_number_and_location. */
- static void
- disable_command (const char *args, int from_tty)
- {
- enable_disable_command (args, from_tty, false);
- }
- static void
- enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition,
- int count)
- {
- int target_resources_ok;
- if (bpt->type == bp_hardware_breakpoint)
- {
- int i;
- i = hw_breakpoint_used_count ();
- target_resources_ok =
- target_can_use_hardware_watchpoint (bp_hardware_breakpoint,
- i + 1, 0);
- if (target_resources_ok == 0)
- error (_("No hardware breakpoint support in the target."));
- else if (target_resources_ok < 0)
- error (_("Hardware breakpoints used exceeds limit."));
- }
- if (is_watchpoint (bpt))
- {
- /* Initialize it just to avoid a GCC false warning. */
- enum enable_state orig_enable_state = bp_disabled;
- try
- {
- struct watchpoint *w = (struct watchpoint *) bpt;
- orig_enable_state = bpt->enable_state;
- bpt->enable_state = bp_enabled;
- update_watchpoint (w, 1 /* reparse */);
- }
- catch (const gdb_exception &e)
- {
- bpt->enable_state = orig_enable_state;
- exception_fprintf (gdb_stderr, e, _("Cannot enable watchpoint %d: "),
- bpt->number);
- return;
- }
- }
- bpt->enable_state = bp_enabled;
- /* Mark breakpoint locations modified. */
- mark_breakpoint_modified (bpt);
- if (target_supports_enable_disable_tracepoint ()
- && current_trace_status ()->running && is_tracepoint (bpt))
- {
- for (bp_location *location : bpt->locations ())
- target_enable_tracepoint (location);
- }
- bpt->disposition = disposition;
- bpt->enable_count = count;
- update_global_location_list (UGLL_MAY_INSERT);
- gdb::observers::breakpoint_modified.notify (bpt);
- }
- void
- enable_breakpoint (struct breakpoint *bpt)
- {
- enable_breakpoint_disp (bpt, bpt->disposition, 0);
- }
- /* The enable command enables the specified breakpoints/locations (or
- all defined breakpoints) so they once again become (or continue to
- be) effective in stopping the inferior. ARGS may be in any of the
- forms defined in extract_bp_number_and_location. */
- static void
- enable_command (const char *args, int from_tty)
- {
- enable_disable_command (args, from_tty, true);
- }
- static void
- enable_once_command (const char *args, int from_tty)
- {
- map_breakpoint_numbers
- (args, [&] (breakpoint *b)
- {
- iterate_over_related_breakpoints
- (b, [&] (breakpoint *bpt)
- {
- enable_breakpoint_disp (bpt, disp_disable, 1);
- });
- });
- }
- static void
- enable_count_command (const char *args, int from_tty)
- {
- int count;
- if (args == NULL)
- error_no_arg (_("hit count"));
- count = get_number (&args);
- map_breakpoint_numbers
- (args, [&] (breakpoint *b)
- {
- iterate_over_related_breakpoints
- (b, [&] (breakpoint *bpt)
- {
- enable_breakpoint_disp (bpt, disp_disable, count);
- });
- });
- }
- static void
- enable_delete_command (const char *args, int from_tty)
- {
- map_breakpoint_numbers
- (args, [&] (breakpoint *b)
- {
- iterate_over_related_breakpoints
- (b, [&] (breakpoint *bpt)
- {
- enable_breakpoint_disp (bpt, disp_del, 1);
- });
- });
- }
- /* Invalidate last known value of any hardware watchpoint if
- the memory which that value represents has been written to by
- GDB itself. */
- static void
- invalidate_bp_value_on_memory_change (struct inferior *inferior,
- CORE_ADDR addr, ssize_t len,
- const bfd_byte *data)
- {
- for (breakpoint *bp : all_breakpoints ())
- if (bp->enable_state == bp_enabled
- && bp->type == bp_hardware_watchpoint)
- {
- struct watchpoint *wp = (struct watchpoint *) bp;
- if (wp->val_valid && wp->val != nullptr)
- {
- for (bp_location *loc : bp->locations ())
- if (loc->loc_type == bp_loc_hardware_watchpoint
- && loc->address + loc->length > addr
- && addr + len > loc->address)
- {
- wp->val = NULL;
- wp->val_valid = false;
- }
- }
- }
- }
- /* Create and insert a breakpoint for software single step. */
- void
- insert_single_step_breakpoint (struct gdbarch *gdbarch,
- const address_space *aspace,
- CORE_ADDR next_pc)
- {
- struct thread_info *tp = inferior_thread ();
- struct symtab_and_line sal;
- CORE_ADDR pc = next_pc;
- if (tp->control.single_step_breakpoints == NULL)
- {
- tp->control.single_step_breakpoints
- = new_single_step_breakpoint (tp->global_num, gdbarch);
- }
- sal = find_pc_line (pc, 0);
- sal.pc = pc;
- sal.section = find_pc_overlay (pc);
- sal.explicit_pc = 1;
- add_location_to_breakpoint (tp->control.single_step_breakpoints, &sal);
- update_global_location_list (UGLL_INSERT);
- }
- /* Insert single step breakpoints according to the current state. */
- int
- insert_single_step_breakpoints (struct gdbarch *gdbarch)
- {
- struct regcache *regcache = get_current_regcache ();
- std::vector<CORE_ADDR> next_pcs;
- next_pcs = gdbarch_software_single_step (gdbarch, regcache);
- if (!next_pcs.empty ())
- {
- struct frame_info *frame = get_current_frame ();
- const address_space *aspace = get_frame_address_space (frame);
- for (CORE_ADDR pc : next_pcs)
- insert_single_step_breakpoint (gdbarch, aspace, pc);
- return 1;
- }
- else
- return 0;
- }
- /* See breakpoint.h. */
- int
- breakpoint_has_location_inserted_here (struct breakpoint *bp,
- const address_space *aspace,
- CORE_ADDR pc)
- {
- for (bp_location *loc : bp->locations ())
- if (loc->inserted
- && breakpoint_location_address_match (loc, aspace, pc))
- return 1;
- return 0;
- }
- /* Check whether a software single-step breakpoint is inserted at
- PC. */
- int
- single_step_breakpoint_inserted_here_p (const address_space *aspace,
- CORE_ADDR pc)
- {
- for (breakpoint *bpt : all_breakpoints ())
- {
- if (bpt->type == bp_single_step
- && breakpoint_has_location_inserted_here (bpt, aspace, pc))
- return 1;
- }
- return 0;
- }
- /* Tracepoint-specific operations. */
- /* Set tracepoint count to NUM. */
- static void
- set_tracepoint_count (int num)
- {
- tracepoint_count = num;
- set_internalvar_integer (lookup_internalvar ("tpnum"), num);
- }
- static void
- trace_command (const char *arg, int from_tty)
- {
- event_location_up location = string_to_event_location (&arg,
- current_language);
- const struct breakpoint_ops *ops = breakpoint_ops_for_event_location
- (location.get (), true /* is_tracepoint */);
- create_breakpoint (get_current_arch (),
- location.get (),
- NULL, 0, arg, false, 1 /* parse arg */,
- 0 /* tempflag */,
- bp_tracepoint /* type_wanted */,
- 0 /* Ignore count */,
- pending_break_support,
- ops,
- from_tty,
- 1 /* enabled */,
- 0 /* internal */, 0);
- }
- static void
- ftrace_command (const char *arg, int from_tty)
- {
- event_location_up location = string_to_event_location (&arg,
- current_language);
- create_breakpoint (get_current_arch (),
- location.get (),
- NULL, 0, arg, false, 1 /* parse arg */,
- 0 /* tempflag */,
- bp_fast_tracepoint /* type_wanted */,
- 0 /* Ignore count */,
- pending_break_support,
- &tracepoint_breakpoint_ops,
- from_tty,
- 1 /* enabled */,
- 0 /* internal */, 0);
- }
- /* strace command implementation. Creates a static tracepoint. */
- static void
- strace_command (const char *arg, int from_tty)
- {
- struct breakpoint_ops *ops;
- event_location_up location;
- /* Decide if we are dealing with a static tracepoint marker (`-m'),
- or with a normal static tracepoint. */
- if (arg && startswith (arg, "-m") && isspace (arg[2]))
- {
- ops = &strace_marker_breakpoint_ops;
- location = new_linespec_location (&arg, symbol_name_match_type::FULL);
- }
- else
- {
- ops = &tracepoint_breakpoint_ops;
- location = string_to_event_location (&arg, current_language);
- }
- create_breakpoint (get_current_arch (),
- location.get (),
- NULL, 0, arg, false, 1 /* parse arg */,
- 0 /* tempflag */,
- bp_static_tracepoint /* type_wanted */,
- 0 /* Ignore count */,
- pending_break_support,
- ops,
- from_tty,
- 1 /* enabled */,
- 0 /* internal */, 0);
- }
- /* Set up a fake reader function that gets command lines from a linked
- list that was acquired during tracepoint uploading. */
- static struct uploaded_tp *this_utp;
- static int next_cmd;
- static char *
- read_uploaded_action (void)
- {
- char *rslt = nullptr;
- if (next_cmd < this_utp->cmd_strings.size ())
- {
- rslt = this_utp->cmd_strings[next_cmd].get ();
- next_cmd++;
- }
- return rslt;
- }
- /* Given information about a tracepoint as recorded on a target (which
- can be either a live system or a trace file), attempt to create an
- equivalent GDB tracepoint. This is not a reliable process, since
- the target does not necessarily have all the information used when
- the tracepoint was originally defined. */
-
- struct tracepoint *
- create_tracepoint_from_upload (struct uploaded_tp *utp)
- {
- const char *addr_str;
- char small_buf[100];
- struct tracepoint *tp;
- if (utp->at_string)
- addr_str = utp->at_string.get ();
- else
- {
- /* In the absence of a source location, fall back to raw
- address. Since there is no way to confirm that the address
- means the same thing as when the trace was started, warn the
- user. */
- warning (_("Uploaded tracepoint %d has no "
- "source location, using raw address"),
- utp->number);
- xsnprintf (small_buf, sizeof (small_buf), "*%s", hex_string (utp->addr));
- addr_str = small_buf;
- }
- /* There's not much we can do with a sequence of bytecodes. */
- if (utp->cond && !utp->cond_string)
- warning (_("Uploaded tracepoint %d condition "
- "has no source form, ignoring it"),
- utp->number);
- event_location_up location = string_to_event_location (&addr_str,
- current_language);
- if (!create_breakpoint (get_current_arch (),
- location.get (),
- utp->cond_string.get (), -1, addr_str,
- false /* force_condition */,
- 0 /* parse cond/thread */,
- 0 /* tempflag */,
- utp->type /* type_wanted */,
- 0 /* Ignore count */,
- pending_break_support,
- &tracepoint_breakpoint_ops,
- 0 /* from_tty */,
- utp->enabled /* enabled */,
- 0 /* internal */,
- CREATE_BREAKPOINT_FLAGS_INSERTED))
- return NULL;
- /* Get the tracepoint we just created. */
- tp = get_tracepoint (tracepoint_count);
- gdb_assert (tp != NULL);
- if (utp->pass > 0)
- {
- xsnprintf (small_buf, sizeof (small_buf), "%d %d", utp->pass,
- tp->number);
- trace_pass_command (small_buf, 0);
- }
- /* If we have uploaded versions of the original commands, set up a
- special-purpose "reader" function and call the usual command line
- reader, then pass the result to the breakpoint command-setting
- function. */
- if (!utp->cmd_strings.empty ())
- {
- counted_command_line cmd_list;
- this_utp = utp;
- next_cmd = 0;
- cmd_list = read_command_lines_1 (read_uploaded_action, 1, NULL);
- breakpoint_set_commands (tp, std::move (cmd_list));
- }
- else if (!utp->actions.empty ()
- || !utp->step_actions.empty ())
- warning (_("Uploaded tracepoint %d actions "
- "have no source form, ignoring them"),
- utp->number);
- /* Copy any status information that might be available. */
- tp->hit_count = utp->hit_count;
- tp->traceframe_usage = utp->traceframe_usage;
- return tp;
- }
-
- /* Print information on tracepoint number TPNUM_EXP, or all if
- omitted. */
- static void
- info_tracepoints_command (const char *args, int from_tty)
- {
- struct ui_out *uiout = current_uiout;
- int num_printed;
- num_printed = breakpoint_1 (args, false, is_tracepoint);
- if (num_printed == 0)
- {
- if (args == NULL || *args == '\0')
- uiout->message ("No tracepoints.\n");
- else
- uiout->message ("No tracepoint matching '%s'.\n", args);
- }
- default_collect_info ();
- }
- /* The 'enable trace' command enables tracepoints.
- Not supported by all targets. */
- static void
- enable_trace_command (const char *args, int from_tty)
- {
- enable_command (args, from_tty);
- }
- /* The 'disable trace' command disables tracepoints.
- Not supported by all targets. */
- static void
- disable_trace_command (const char *args, int from_tty)
- {
- disable_command (args, from_tty);
- }
- /* Remove a tracepoint (or all if no argument). */
- static void
- delete_trace_command (const char *arg, int from_tty)
- {
- dont_repeat ();
- if (arg == 0)
- {
- int breaks_to_delete = 0;
- /* Delete all breakpoints if no argument.
- Do not delete internal or call-dummy breakpoints, these
- have to be deleted with an explicit breakpoint number
- argument. */
- for (breakpoint *tp : all_tracepoints ())
- if (is_tracepoint (tp) && user_breakpoint_p (tp))
- {
- breaks_to_delete = 1;
- break;
- }
- /* Ask user only if there are some breakpoints to delete. */
- if (!from_tty
- || (breaks_to_delete && query (_("Delete all tracepoints? "))))
- {
- for (breakpoint *b : all_breakpoints_safe ())
- if (is_tracepoint (b) && user_breakpoint_p (b))
- delete_breakpoint (b);
- }
- }
- else
- map_breakpoint_numbers
- (arg, [&] (breakpoint *br)
- {
- iterate_over_related_breakpoints (br, delete_breakpoint);
- });
- }
- /* Helper function for trace_pass_command. */
- static void
- trace_pass_set_count (struct tracepoint *tp, int count, int from_tty)
- {
- tp->pass_count = count;
- gdb::observers::breakpoint_modified.notify (tp);
- if (from_tty)
- gdb_printf (_("Setting tracepoint %d's passcount to %d\n"),
- tp->number, count);
- }
- /* Set passcount for tracepoint.
- First command argument is passcount, second is tracepoint number.
- If tracepoint number omitted, apply to most recently defined.
- Also accepts special argument "all". */
- static void
- trace_pass_command (const char *args, int from_tty)
- {
- struct tracepoint *t1;
- ULONGEST count;
- if (args == 0 || *args == 0)
- error (_("passcount command requires an "
- "argument (count + optional TP num)"));
- count = strtoulst (args, &args, 10); /* Count comes first, then TP num. */
- args = skip_spaces (args);
- if (*args && strncasecmp (args, "all", 3) == 0)
- {
- args += 3; /* Skip special argument "all". */
- if (*args)
- error (_("Junk at end of arguments."));
- for (breakpoint *b : all_tracepoints ())
- {
- t1 = (struct tracepoint *) b;
- trace_pass_set_count (t1, count, from_tty);
- }
- }
- else if (*args == '\0')
- {
- t1 = get_tracepoint_by_number (&args, NULL);
- if (t1)
- trace_pass_set_count (t1, count, from_tty);
- }
- else
- {
- number_or_range_parser parser (args);
- while (!parser.finished ())
- {
- t1 = get_tracepoint_by_number (&args, &parser);
- if (t1)
- trace_pass_set_count (t1, count, from_tty);
- }
- }
- }
- struct tracepoint *
- get_tracepoint (int num)
- {
- for (breakpoint *t : all_tracepoints ())
- if (t->number == num)
- return (struct tracepoint *) t;
- return NULL;
- }
- /* Find the tracepoint with the given target-side number (which may be
- different from the tracepoint number after disconnecting and
- reconnecting). */
- struct tracepoint *
- get_tracepoint_by_number_on_target (int num)
- {
- for (breakpoint *b : all_tracepoints ())
- {
- struct tracepoint *t = (struct tracepoint *) b;
- if (t->number_on_target == num)
- return t;
- }
- return NULL;
- }
- /* Utility: parse a tracepoint number and look it up in the list.
- If STATE is not NULL, use, get_number_or_range_state and ignore ARG.
- If the argument is missing, the most recent tracepoint
- (tracepoint_count) is returned. */
- struct tracepoint *
- get_tracepoint_by_number (const char **arg,
- number_or_range_parser *parser)
- {
- int tpnum;
- const char *instring = arg == NULL ? NULL : *arg;
- if (parser != NULL)
- {
- gdb_assert (!parser->finished ());
- tpnum = parser->get_number ();
- }
- else if (arg == NULL || *arg == NULL || ! **arg)
- tpnum = tracepoint_count;
- else
- tpnum = get_number (arg);
- if (tpnum <= 0)
- {
- if (instring && *instring)
- gdb_printf (_("bad tracepoint number at or near '%s'\n"),
- instring);
- else
- gdb_printf (_("No previous tracepoint\n"));
- return NULL;
- }
- for (breakpoint *t : all_tracepoints ())
- if (t->number == tpnum)
- return (struct tracepoint *) t;
- gdb_printf ("No tracepoint number %d.\n", tpnum);
- return NULL;
- }
- void
- print_recreate_thread (struct breakpoint *b, struct ui_file *fp)
- {
- if (b->thread != -1)
- gdb_printf (fp, " thread %d", b->thread);
- if (b->task != 0)
- gdb_printf (fp, " task %d", b->task);
- gdb_printf (fp, "\n");
- }
- /* Save information on user settable breakpoints (watchpoints, etc) to
- a new script file named FILENAME. If FILTER is non-NULL, call it
- on each breakpoint and only include the ones for which it returns
- true. */
- static void
- save_breakpoints (const char *filename, int from_tty,
- bool (*filter) (const struct breakpoint *))
- {
- int any = 0;
- int extra_trace_bits = 0;
- if (filename == 0 || *filename == 0)
- error (_("Argument required (file name in which to save)"));
- /* See if we have anything to save. */
- for (breakpoint *tp : all_breakpoints ())
- {
- /* Skip internal and momentary breakpoints. */
- if (!user_breakpoint_p (tp))
- continue;
- /* If we have a filter, only save the breakpoints it accepts. */
- if (filter && !filter (tp))
- continue;
- any = 1;
- if (is_tracepoint (tp))
- {
- extra_trace_bits = 1;
- /* We can stop searching. */
- break;
- }
- }
- if (!any)
- {
- warning (_("Nothing to save."));
- return;
- }
- gdb::unique_xmalloc_ptr<char> expanded_filename (tilde_expand (filename));
- stdio_file fp;
- if (!fp.open (expanded_filename.get (), "w"))
- error (_("Unable to open file '%s' for saving (%s)"),
- expanded_filename.get (), safe_strerror (errno));
- if (extra_trace_bits)
- save_trace_state_variables (&fp);
- for (breakpoint *tp : all_breakpoints ())
- {
- /* Skip internal and momentary breakpoints. */
- if (!user_breakpoint_p (tp))
- continue;
- /* If we have a filter, only save the breakpoints it accepts. */
- if (filter && !filter (tp))
- continue;
- tp->ops->print_recreate (tp, &fp);
- /* Note, we can't rely on tp->number for anything, as we can't
- assume the recreated breakpoint numbers will match. Use $bpnum
- instead. */
- if (tp->cond_string)
- fp.printf (" condition $bpnum %s\n", tp->cond_string.get ());
- if (tp->ignore_count)
- fp.printf (" ignore $bpnum %d\n", tp->ignore_count);
- if (tp->type != bp_dprintf && tp->commands)
- {
- fp.puts (" commands\n");
- current_uiout->redirect (&fp);
- try
- {
- print_command_lines (current_uiout, tp->commands.get (), 2);
- }
- catch (const gdb_exception &ex)
- {
- current_uiout->redirect (NULL);
- throw;
- }
- current_uiout->redirect (NULL);
- fp.puts (" end\n");
- }
- if (tp->enable_state == bp_disabled)
- fp.puts ("disable $bpnum\n");
- /* If this is a multi-location breakpoint, check if the locations
- should be individually disabled. Watchpoint locations are
- special, and not user visible. */
- if (!is_watchpoint (tp) && tp->loc && tp->loc->next)
- {
- int n = 1;
- for (bp_location *loc : tp->locations ())
- {
- if (!loc->enabled)
- fp.printf ("disable $bpnum.%d\n", n);
- n++;
- }
- }
- }
- if (extra_trace_bits && !default_collect.empty ())
- fp.printf ("set default-collect %s\n", default_collect.c_str ());
- if (from_tty)
- gdb_printf (_("Saved to file '%s'.\n"), expanded_filename.get ());
- }
- /* The `save breakpoints' command. */
- static void
- save_breakpoints_command (const char *args, int from_tty)
- {
- save_breakpoints (args, from_tty, NULL);
- }
- /* The `save tracepoints' command. */
- static void
- save_tracepoints_command (const char *args, int from_tty)
- {
- save_breakpoints (args, from_tty, is_tracepoint);
- }
- /* This help string is used to consolidate all the help string for specifying
- locations used by several commands. */
- #define LOCATION_HELP_STRING \
- "Linespecs are colon-separated lists of location parameters, such as\n\
- source filename, function name, label name, and line number.\n\
- Example: To specify the start of a label named \"the_top\" in the\n\
- function \"fact\" in the file \"factorial.c\", use\n\
- \"factorial.c:fact:the_top\".\n\
- \n\
- Address locations begin with \"*\" and specify an exact address in the\n\
- program. Example: To specify the fourth byte past the start function\n\
- \"main\", use \"*main + 4\".\n\
- \n\
- Explicit locations are similar to linespecs but use an option/argument\n\
- syntax to specify location parameters.\n\
- Example: To specify the start of the label named \"the_top\" in the\n\
- function \"fact\" in the file \"factorial.c\", use \"-source factorial.c\n\
- -function fact -label the_top\".\n\
- \n\
- By default, a specified function is matched against the program's\n\
- functions in all scopes. For C++, this means in all namespaces and\n\
- classes. For Ada, this means in all packages. E.g., in C++,\n\
- \"func()\" matches \"A::func()\", \"A::B::func()\", etc. The\n\
- \"-qualified\" flag overrides this behavior, making GDB interpret the\n\
- specified name as a complete fully-qualified name instead."
- /* This help string is used for the break, hbreak, tbreak and thbreak
- commands. It is defined as a macro to prevent duplication.
- COMMAND should be a string constant containing the name of the
- command. */
- #define BREAK_ARGS_HELP(command) \
- command" [PROBE_MODIFIER] [LOCATION] [thread THREADNUM]\n\
- \t[-force-condition] [if CONDITION]\n\
- PROBE_MODIFIER shall be present if the command is to be placed in a\n\
- probe point. Accepted values are `-probe' (for a generic, automatically\n\
- guessed probe type), `-probe-stap' (for a SystemTap probe) or \n\
- `-probe-dtrace' (for a DTrace probe).\n\
- LOCATION may be a linespec, address, or explicit location as described\n\
- below.\n\
- \n\
- With no LOCATION, uses current execution address of the selected\n\
- stack frame. This is useful for breaking on return to a stack frame.\n\
- \n\
- THREADNUM is the number from \"info threads\".\n\
- CONDITION is a boolean expression.\n\
- \n\
- With the \"-force-condition\" flag, the condition is defined even when\n\
- it is invalid for all current locations.\n\
- \n" LOCATION_HELP_STRING "\n\n\
- Multiple breakpoints at one place are permitted, and useful if their\n\
- conditions are different.\n\
- \n\
- Do \"help breakpoints\" for info on other commands dealing with breakpoints."
- /* List of subcommands for "catch". */
- static struct cmd_list_element *catch_cmdlist;
- /* List of subcommands for "tcatch". */
- static struct cmd_list_element *tcatch_cmdlist;
- void
- add_catch_command (const char *name, const char *docstring,
- cmd_func_ftype *func,
- completer_ftype *completer,
- void *user_data_catch,
- void *user_data_tcatch)
- {
- struct cmd_list_element *command;
- command = add_cmd (name, class_breakpoint, docstring,
- &catch_cmdlist);
- command->func = func;
- command->set_context (user_data_catch);
- set_cmd_completer (command, completer);
- command = add_cmd (name, class_breakpoint, docstring,
- &tcatch_cmdlist);
- command->func = func;
- command->set_context (user_data_tcatch);
- set_cmd_completer (command, completer);
- }
- /* Zero if any of the breakpoint's locations could be a location where
- functions have been inlined, nonzero otherwise. */
- static int
- is_non_inline_function (struct breakpoint *b)
- {
- /* The shared library event breakpoint is set on the address of a
- non-inline function. */
- if (b->type == bp_shlib_event)
- return 1;
- return 0;
- }
- /* Nonzero if the specified PC cannot be a location where functions
- have been inlined. */
- int
- pc_at_non_inline_function (const address_space *aspace, CORE_ADDR pc,
- const target_waitstatus &ws)
- {
- for (breakpoint *b : all_breakpoints ())
- {
- if (!is_non_inline_function (b))
- continue;
- for (bp_location *bl : b->locations ())
- {
- if (!bl->shlib_disabled
- && bpstat_check_location (bl, aspace, pc, ws))
- return 1;
- }
- }
- return 0;
- }
- /* Remove any references to OBJFILE which is going to be freed. */
- void
- breakpoint_free_objfile (struct objfile *objfile)
- {
- for (bp_location *loc : all_bp_locations ())
- if (loc->symtab != NULL && loc->symtab->compunit ()->objfile () == objfile)
- loc->symtab = NULL;
- }
- void
- initialize_breakpoint_ops (void)
- {
- static int initialized = 0;
- struct breakpoint_ops *ops;
- if (initialized)
- return;
- initialized = 1;
- /* The breakpoint_ops structure to be inherit by all kinds of
- breakpoints (real breakpoints, i.e., user "break" breakpoints,
- internal and momentary breakpoints, etc.). */
- ops = &bkpt_base_breakpoint_ops;
- *ops = base_breakpoint_ops;
- ops->re_set = bkpt_re_set;
- ops->insert_location = bkpt_insert_location;
- ops->remove_location = bkpt_remove_location;
- ops->breakpoint_hit = bkpt_breakpoint_hit;
- ops->create_sals_from_location = bkpt_create_sals_from_location;
- ops->create_breakpoints_sal = bkpt_create_breakpoints_sal;
- ops->decode_location = bkpt_decode_location;
- /* The breakpoint_ops structure to be used in regular breakpoints. */
- ops = &bkpt_breakpoint_ops;
- *ops = bkpt_base_breakpoint_ops;
- ops->re_set = bkpt_re_set;
- ops->resources_needed = bkpt_resources_needed;
- ops->print_it = bkpt_print_it;
- ops->print_mention = bkpt_print_mention;
- ops->print_recreate = bkpt_print_recreate;
- /* Ranged breakpoints. */
- ops = &ranged_breakpoint_ops;
- *ops = bkpt_breakpoint_ops;
- ops->breakpoint_hit = breakpoint_hit_ranged_breakpoint;
- ops->resources_needed = resources_needed_ranged_breakpoint;
- ops->print_it = print_it_ranged_breakpoint;
- ops->print_one = print_one_ranged_breakpoint;
- ops->print_one_detail = print_one_detail_ranged_breakpoint;
- ops->print_mention = print_mention_ranged_breakpoint;
- ops->print_recreate = print_recreate_ranged_breakpoint;
- /* Internal breakpoints. */
- ops = &internal_breakpoint_ops;
- *ops = bkpt_base_breakpoint_ops;
- ops->re_set = internal_bkpt_re_set;
- ops->check_status = internal_bkpt_check_status;
- ops->print_it = internal_bkpt_print_it;
- ops->print_mention = internal_bkpt_print_mention;
- /* Momentary breakpoints. */
- ops = &momentary_breakpoint_ops;
- *ops = bkpt_base_breakpoint_ops;
- ops->re_set = momentary_bkpt_re_set;
- ops->check_status = momentary_bkpt_check_status;
- ops->print_it = momentary_bkpt_print_it;
- ops->print_mention = momentary_bkpt_print_mention;
- /* Probe breakpoints. */
- ops = &bkpt_probe_breakpoint_ops;
- *ops = bkpt_breakpoint_ops;
- ops->insert_location = bkpt_probe_insert_location;
- ops->remove_location = bkpt_probe_remove_location;
- ops->create_sals_from_location = bkpt_probe_create_sals_from_location;
- ops->decode_location = bkpt_probe_decode_location;
- /* Watchpoints. */
- ops = &watchpoint_breakpoint_ops;
- *ops = base_breakpoint_ops;
- ops->re_set = re_set_watchpoint;
- ops->insert_location = insert_watchpoint;
- ops->remove_location = remove_watchpoint;
- ops->breakpoint_hit = breakpoint_hit_watchpoint;
- ops->check_status = check_status_watchpoint;
- ops->resources_needed = resources_needed_watchpoint;
- ops->works_in_software_mode = works_in_software_mode_watchpoint;
- ops->print_it = print_it_watchpoint;
- ops->print_mention = print_mention_watchpoint;
- ops->print_recreate = print_recreate_watchpoint;
- ops->explains_signal = explains_signal_watchpoint;
- /* Masked watchpoints. */
- ops = &masked_watchpoint_breakpoint_ops;
- *ops = watchpoint_breakpoint_ops;
- ops->insert_location = insert_masked_watchpoint;
- ops->remove_location = remove_masked_watchpoint;
- ops->resources_needed = resources_needed_masked_watchpoint;
- ops->works_in_software_mode = works_in_software_mode_masked_watchpoint;
- ops->print_it = print_it_masked_watchpoint;
- ops->print_one_detail = print_one_detail_masked_watchpoint;
- ops->print_mention = print_mention_masked_watchpoint;
- ops->print_recreate = print_recreate_masked_watchpoint;
- /* Tracepoints. */
- ops = &tracepoint_breakpoint_ops;
- *ops = base_breakpoint_ops;
- ops->re_set = tracepoint_re_set;
- ops->breakpoint_hit = tracepoint_breakpoint_hit;
- ops->print_one_detail = tracepoint_print_one_detail;
- ops->print_mention = tracepoint_print_mention;
- ops->print_recreate = tracepoint_print_recreate;
- ops->create_sals_from_location = tracepoint_create_sals_from_location;
- ops->create_breakpoints_sal = tracepoint_create_breakpoints_sal;
- ops->decode_location = tracepoint_decode_location;
- /* Probe tracepoints. */
- ops = &tracepoint_probe_breakpoint_ops;
- *ops = tracepoint_breakpoint_ops;
- ops->create_sals_from_location = tracepoint_probe_create_sals_from_location;
- ops->decode_location = tracepoint_probe_decode_location;
- /* Static tracepoints with marker (`-m'). */
- ops = &strace_marker_breakpoint_ops;
- *ops = tracepoint_breakpoint_ops;
- ops->create_sals_from_location = strace_marker_create_sals_from_location;
- ops->create_breakpoints_sal = strace_marker_create_breakpoints_sal;
- ops->decode_location = strace_marker_decode_location;
- /* Solib-related catchpoints. */
- ops = &catch_solib_breakpoint_ops;
- *ops = base_breakpoint_ops;
- ops->insert_location = insert_catch_solib;
- ops->remove_location = remove_catch_solib;
- ops->breakpoint_hit = breakpoint_hit_catch_solib;
- ops->check_status = check_status_catch_solib;
- ops->print_it = print_it_catch_solib;
- ops->print_one = print_one_catch_solib;
- ops->print_mention = print_mention_catch_solib;
- ops->print_recreate = print_recreate_catch_solib;
- ops = &dprintf_breakpoint_ops;
- *ops = bkpt_base_breakpoint_ops;
- ops->re_set = dprintf_re_set;
- ops->resources_needed = bkpt_resources_needed;
- ops->print_it = bkpt_print_it;
- ops->print_mention = bkpt_print_mention;
- ops->print_recreate = dprintf_print_recreate;
- ops->after_condition_true = dprintf_after_condition_true;
- ops->breakpoint_hit = dprintf_breakpoint_hit;
- }
- /* Chain containing all defined "enable breakpoint" subcommands. */
- static struct cmd_list_element *enablebreaklist = NULL;
- /* See breakpoint.h. */
- cmd_list_element *commands_cmd_element = nullptr;
- void _initialize_breakpoint ();
- void
- _initialize_breakpoint ()
- {
- struct cmd_list_element *c;
- initialize_breakpoint_ops ();
- gdb::observers::solib_unloaded.attach (disable_breakpoints_in_unloaded_shlib,
- "breakpoint");
- gdb::observers::free_objfile.attach (disable_breakpoints_in_freed_objfile,
- "breakpoint");
- gdb::observers::memory_changed.attach (invalidate_bp_value_on_memory_change,
- "breakpoint");
- breakpoint_chain = 0;
- /* Don't bother to call set_breakpoint_count. $bpnum isn't useful
- before a breakpoint is set. */
- breakpoint_count = 0;
- tracepoint_count = 0;
- add_com ("ignore", class_breakpoint, ignore_command, _("\
- Set ignore-count of breakpoint number N to COUNT.\n\
- Usage is `ignore N COUNT'."));
- commands_cmd_element = add_com ("commands", class_breakpoint,
- commands_command, _("\
- Set commands to be executed when the given breakpoints are hit.\n\
- Give a space-separated breakpoint list as argument after \"commands\".\n\
- A list element can be a breakpoint number (e.g. `5') or a range of numbers\n\
- (e.g. `5-7').\n\
- With no argument, the targeted breakpoint is the last one set.\n\
- The commands themselves follow starting on the next line.\n\
- Type a line containing \"end\" to indicate the end of them.\n\
- Give \"silent\" as the first line to make the breakpoint silent;\n\
- then no output is printed when it is hit, except what the commands print."));
- const auto cc_opts = make_condition_command_options_def_group (nullptr);
- static std::string condition_command_help
- = gdb::option::build_help (_("\
- Specify breakpoint number N to break only if COND is true.\n\
- Usage is `condition [OPTION] N COND', where N is an integer and COND\n\
- is an expression to be evaluated whenever breakpoint N is reached.\n\
- \n\
- Options:\n\
- %OPTIONS%"), cc_opts);
- c = add_com ("condition", class_breakpoint, condition_command,
- condition_command_help.c_str ());
- set_cmd_completer_handle_brkchars (c, condition_completer);
- c = add_com ("tbreak", class_breakpoint, tbreak_command, _("\
- Set a temporary breakpoint.\n\
- Like \"break\" except the breakpoint is only temporary,\n\
- so it will be deleted when hit. Equivalent to \"break\" followed\n\
- by using \"enable delete\" on the breakpoint number.\n\
- \n"
- BREAK_ARGS_HELP ("tbreak")));
- set_cmd_completer (c, location_completer);
- c = add_com ("hbreak", class_breakpoint, hbreak_command, _("\
- Set a hardware assisted breakpoint.\n\
- Like \"break\" except the breakpoint requires hardware support,\n\
- some target hardware may not have this support.\n\
- \n"
- BREAK_ARGS_HELP ("hbreak")));
- set_cmd_completer (c, location_completer);
- c = add_com ("thbreak", class_breakpoint, thbreak_command, _("\
- Set a temporary hardware assisted breakpoint.\n\
- Like \"hbreak\" except the breakpoint is only temporary,\n\
- so it will be deleted when hit.\n\
- \n"
- BREAK_ARGS_HELP ("thbreak")));
- set_cmd_completer (c, location_completer);
- cmd_list_element *enable_cmd
- = add_prefix_cmd ("enable", class_breakpoint, enable_command, _("\
- Enable all or some breakpoints.\n\
- Usage: enable [BREAKPOINTNUM]...\n\
- Give breakpoint numbers (separated by spaces) as arguments.\n\
- With no subcommand, breakpoints are enabled until you command otherwise.\n\
- This is used to cancel the effect of the \"disable\" command.\n\
- With a subcommand you can enable temporarily."),
- &enablelist, 1, &cmdlist);
- add_com_alias ("en", enable_cmd, class_breakpoint, 1);
- add_prefix_cmd ("breakpoints", class_breakpoint, enable_command, _("\
- Enable all or some breakpoints.\n\
- Usage: enable breakpoints [BREAKPOINTNUM]...\n\
- Give breakpoint numbers (separated by spaces) as arguments.\n\
- This is used to cancel the effect of the \"disable\" command.\n\
- May be abbreviated to simply \"enable\"."),
- &enablebreaklist, 1, &enablelist);
- add_cmd ("once", no_class, enable_once_command, _("\
- Enable some breakpoints for one hit.\n\
- Usage: enable breakpoints once BREAKPOINTNUM...\n\
- If a breakpoint is hit while enabled in this fashion, it becomes disabled."),
- &enablebreaklist);
- add_cmd ("delete", no_class, enable_delete_command, _("\
- Enable some breakpoints and delete when hit.\n\
- Usage: enable breakpoints delete BREAKPOINTNUM...\n\
- If a breakpoint is hit while enabled in this fashion, it is deleted."),
- &enablebreaklist);
- add_cmd ("count", no_class, enable_count_command, _("\
- Enable some breakpoints for COUNT hits.\n\
- Usage: enable breakpoints count COUNT BREAKPOINTNUM...\n\
- If a breakpoint is hit while enabled in this fashion,\n\
- the count is decremented; when it reaches zero, the breakpoint is disabled."),
- &enablebreaklist);
- add_cmd ("delete", no_class, enable_delete_command, _("\
- Enable some breakpoints and delete when hit.\n\
- Usage: enable delete BREAKPOINTNUM...\n\
- If a breakpoint is hit while enabled in this fashion, it is deleted."),
- &enablelist);
- add_cmd ("once", no_class, enable_once_command, _("\
- Enable some breakpoints for one hit.\n\
- Usage: enable once BREAKPOINTNUM...\n\
- If a breakpoint is hit while enabled in this fashion, it becomes disabled."),
- &enablelist);
- add_cmd ("count", no_class, enable_count_command, _("\
- Enable some breakpoints for COUNT hits.\n\
- Usage: enable count COUNT BREAKPOINTNUM...\n\
- If a breakpoint is hit while enabled in this fashion,\n\
- the count is decremented; when it reaches zero, the breakpoint is disabled."),
- &enablelist);
- cmd_list_element *disable_cmd
- = add_prefix_cmd ("disable", class_breakpoint, disable_command, _("\
- Disable all or some breakpoints.\n\
- Usage: disable [BREAKPOINTNUM]...\n\
- Arguments are breakpoint numbers with spaces in between.\n\
- To disable all breakpoints, give no argument.\n\
- A disabled breakpoint is not forgotten, but has no effect until re-enabled."),
- &disablelist, 1, &cmdlist);
- add_com_alias ("dis", disable_cmd, class_breakpoint, 1);
- add_com_alias ("disa", disable_cmd, class_breakpoint, 1);
- add_cmd ("breakpoints", class_breakpoint, disable_command, _("\
- Disable all or some breakpoints.\n\
- Usage: disable breakpoints [BREAKPOINTNUM]...\n\
- Arguments are breakpoint numbers with spaces in between.\n\
- To disable all breakpoints, give no argument.\n\
- A disabled breakpoint is not forgotten, but has no effect until re-enabled.\n\
- This command may be abbreviated \"disable\"."),
- &disablelist);
- cmd_list_element *delete_cmd
- = add_prefix_cmd ("delete", class_breakpoint, delete_command, _("\
- Delete all or some breakpoints.\n\
- Usage: delete [BREAKPOINTNUM]...\n\
- Arguments are breakpoint numbers with spaces in between.\n\
- To delete all breakpoints, give no argument.\n\
- \n\
- Also a prefix command for deletion of other GDB objects."),
- &deletelist, 1, &cmdlist);
- add_com_alias ("d", delete_cmd, class_breakpoint, 1);
- add_com_alias ("del", delete_cmd, class_breakpoint, 1);
- add_cmd ("breakpoints", class_breakpoint, delete_command, _("\
- Delete all or some breakpoints or auto-display expressions.\n\
- Usage: delete breakpoints [BREAKPOINTNUM]...\n\
- Arguments are breakpoint numbers with spaces in between.\n\
- To delete all breakpoints, give no argument.\n\
- This command may be abbreviated \"delete\"."),
- &deletelist);
- cmd_list_element *clear_cmd
- = add_com ("clear", class_breakpoint, clear_command, _("\
- Clear breakpoint at specified location.\n\
- Argument may be a linespec, explicit, or address location as described below.\n\
- \n\
- With no argument, clears all breakpoints in the line that the selected frame\n\
- is executing in.\n"
- "\n" LOCATION_HELP_STRING "\n\n\
- See also the \"delete\" command which clears breakpoints by number."));
- add_com_alias ("cl", clear_cmd, class_breakpoint, 1);
- cmd_list_element *break_cmd
- = add_com ("break", class_breakpoint, break_command, _("\
- Set breakpoint at specified location.\n"
- BREAK_ARGS_HELP ("break")));
- set_cmd_completer (break_cmd, location_completer);
- add_com_alias ("b", break_cmd, class_run, 1);
- add_com_alias ("br", break_cmd, class_run, 1);
- add_com_alias ("bre", break_cmd, class_run, 1);
- add_com_alias ("brea", break_cmd, class_run, 1);
- cmd_list_element *info_breakpoints_cmd
- = add_info ("breakpoints", info_breakpoints_command, _("\
- Status of specified breakpoints (all user-settable breakpoints if no argument).\n\
- The \"Type\" column indicates one of:\n\
- \tbreakpoint - normal breakpoint\n\
- \twatchpoint - watchpoint\n\
- The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
- the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
- breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
- address and file/line number respectively.\n\
- \n\
- Convenience variable \"$_\" and default examine address for \"x\"\n\
- are set to the address of the last breakpoint listed unless the command\n\
- is prefixed with \"server \".\n\n\
- Convenience variable \"$bpnum\" contains the number of the last\n\
- breakpoint set."));
- add_info_alias ("b", info_breakpoints_cmd, 1);
- add_cmd ("breakpoints", class_maintenance, maintenance_info_breakpoints, _("\
- Status of all breakpoints, or breakpoint number NUMBER.\n\
- The \"Type\" column indicates one of:\n\
- \tbreakpoint - normal breakpoint\n\
- \twatchpoint - watchpoint\n\
- \tlongjmp - internal breakpoint used to step through longjmp()\n\
- \tlongjmp resume - internal breakpoint at the target of longjmp()\n\
- \tuntil - internal breakpoint used by the \"until\" command\n\
- \tfinish - internal breakpoint used by the \"finish\" command\n\
- The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
- the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
- breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
- address and file/line number respectively.\n\
- \n\
- Convenience variable \"$_\" and default examine address for \"x\"\n\
- are set to the address of the last breakpoint listed unless the command\n\
- is prefixed with \"server \".\n\n\
- Convenience variable \"$bpnum\" contains the number of the last\n\
- breakpoint set."),
- &maintenanceinfolist);
- add_basic_prefix_cmd ("catch", class_breakpoint, _("\
- Set catchpoints to catch events."),
- &catch_cmdlist,
- 0/*allow-unknown*/, &cmdlist);
- add_basic_prefix_cmd ("tcatch", class_breakpoint, _("\
- Set temporary catchpoints to catch events."),
- &tcatch_cmdlist,
- 0/*allow-unknown*/, &cmdlist);
- add_catch_command ("load", _("Catch loads of shared libraries.\n\
- Usage: catch load [REGEX]\n\
- If REGEX is given, only stop for libraries matching the regular expression."),
- catch_load_command_1,
- NULL,
- CATCH_PERMANENT,
- CATCH_TEMPORARY);
- add_catch_command ("unload", _("Catch unloads of shared libraries.\n\
- Usage: catch unload [REGEX]\n\
- If REGEX is given, only stop for libraries matching the regular expression."),
- catch_unload_command_1,
- NULL,
- CATCH_PERMANENT,
- CATCH_TEMPORARY);
- const auto opts = make_watch_options_def_group (nullptr);
- static const std::string watch_help = gdb::option::build_help (_("\
- Set a watchpoint for EXPRESSION.\n\
- Usage: watch [-location] EXPRESSION\n\
- \n\
- Options:\n\
- %OPTIONS%\n\
- \n\
- A watchpoint stops execution of your program whenever the value of\n\
- an expression changes."), opts);
- c = add_com ("watch", class_breakpoint, watch_command,
- watch_help.c_str ());
- set_cmd_completer_handle_brkchars (c, watch_command_completer);
- static const std::string rwatch_help = gdb::option::build_help (_("\
- Set a read watchpoint for EXPRESSION.\n\
- Usage: rwatch [-location] EXPRESSION\n\
- \n\
- Options:\n\
- %OPTIONS%\n\
- \n\
- A read watchpoint stops execution of your program whenever the value of\n\
- an expression is read."), opts);
- c = add_com ("rwatch", class_breakpoint, rwatch_command,
- rwatch_help.c_str ());
- set_cmd_completer_handle_brkchars (c, watch_command_completer);
- static const std::string awatch_help = gdb::option::build_help (_("\
- Set an access watchpoint for EXPRESSION.\n\
- Usage: awatch [-location] EXPRESSION\n\
- \n\
- Options:\n\
- %OPTIONS%\n\
- \n\
- An access watchpoint stops execution of your program whenever the value\n\
- of an expression is either read or written."), opts);
- c = add_com ("awatch", class_breakpoint, awatch_command,
- awatch_help.c_str ());
- set_cmd_completer_handle_brkchars (c, watch_command_completer);
- add_info ("watchpoints", info_watchpoints_command, _("\
- Status of specified watchpoints (all watchpoints if no argument)."));
- /* XXX: cagney/2005-02-23: This should be a boolean, and should
- respond to changes - contrary to the description. */
- add_setshow_zinteger_cmd ("can-use-hw-watchpoints", class_support,
- &can_use_hw_watchpoints, _("\
- Set debugger's willingness to use watchpoint hardware."), _("\
- Show debugger's willingness to use watchpoint hardware."), _("\
- If zero, gdb will not use hardware for new watchpoints, even if\n\
- such is available. (However, any hardware watchpoints that were\n\
- created before setting this to nonzero, will continue to use watchpoint\n\
- hardware.)"),
- NULL,
- show_can_use_hw_watchpoints,
- &setlist, &showlist);
- can_use_hw_watchpoints = 1;
- /* Tracepoint manipulation commands. */
- cmd_list_element *trace_cmd
- = add_com ("trace", class_breakpoint, trace_command, _("\
- Set a tracepoint at specified location.\n\
- \n"
- BREAK_ARGS_HELP ("trace") "\n\
- Do \"help tracepoints\" for info on other tracepoint commands."));
- set_cmd_completer (trace_cmd, location_completer);
- add_com_alias ("tp", trace_cmd, class_breakpoint, 0);
- add_com_alias ("tr", trace_cmd, class_breakpoint, 1);
- add_com_alias ("tra", trace_cmd, class_breakpoint, 1);
- add_com_alias ("trac", trace_cmd, class_breakpoint, 1);
- c = add_com ("ftrace", class_breakpoint, ftrace_command, _("\
- Set a fast tracepoint at specified location.\n\
- \n"
- BREAK_ARGS_HELP ("ftrace") "\n\
- Do \"help tracepoints\" for info on other tracepoint commands."));
- set_cmd_completer (c, location_completer);
- c = add_com ("strace", class_breakpoint, strace_command, _("\
- Set a static tracepoint at location or marker.\n\
- \n\
- strace [LOCATION] [if CONDITION]\n\
- LOCATION may be a linespec, explicit, or address location (described below) \n\
- or -m MARKER_ID.\n\n\
- If a marker id is specified, probe the marker with that name. With\n\
- no LOCATION, uses current execution address of the selected stack frame.\n\
- Static tracepoints accept an extra collect action -- ``collect $_sdata''.\n\
- This collects arbitrary user data passed in the probe point call to the\n\
- tracing library. You can inspect it when analyzing the trace buffer,\n\
- by printing the $_sdata variable like any other convenience variable.\n\
- \n\
- CONDITION is a boolean expression.\n\
- \n" LOCATION_HELP_STRING "\n\n\
- Multiple tracepoints at one place are permitted, and useful if their\n\
- conditions are different.\n\
- \n\
- Do \"help breakpoints\" for info on other commands dealing with breakpoints.\n\
- Do \"help tracepoints\" for info on other tracepoint commands."));
- set_cmd_completer (c, location_completer);
- cmd_list_element *info_tracepoints_cmd
- = add_info ("tracepoints", info_tracepoints_command, _("\
- Status of specified tracepoints (all tracepoints if no argument).\n\
- Convenience variable \"$tpnum\" contains the number of the\n\
- last tracepoint set."));
- add_info_alias ("tp", info_tracepoints_cmd, 1);
- cmd_list_element *delete_tracepoints_cmd
- = add_cmd ("tracepoints", class_trace, delete_trace_command, _("\
- Delete specified tracepoints.\n\
- Arguments are tracepoint numbers, separated by spaces.\n\
- No argument means delete all tracepoints."),
- &deletelist);
- add_alias_cmd ("tr", delete_tracepoints_cmd, class_trace, 1, &deletelist);
- c = add_cmd ("tracepoints", class_trace, disable_trace_command, _("\
- Disable specified tracepoints.\n\
- Arguments are tracepoint numbers, separated by spaces.\n\
- No argument means disable all tracepoints."),
- &disablelist);
- deprecate_cmd (c, "disable");
- c = add_cmd ("tracepoints", class_trace, enable_trace_command, _("\
- Enable specified tracepoints.\n\
- Arguments are tracepoint numbers, separated by spaces.\n\
- No argument means enable all tracepoints."),
- &enablelist);
- deprecate_cmd (c, "enable");
- add_com ("passcount", class_trace, trace_pass_command, _("\
- Set the passcount for a tracepoint.\n\
- The trace will end when the tracepoint has been passed 'count' times.\n\
- Usage: passcount COUNT TPNUM, where TPNUM may also be \"all\";\n\
- if TPNUM is omitted, passcount refers to the last tracepoint defined."));
- add_basic_prefix_cmd ("save", class_breakpoint,
- _("Save breakpoint definitions as a script."),
- &save_cmdlist,
- 0/*allow-unknown*/, &cmdlist);
- c = add_cmd ("breakpoints", class_breakpoint, save_breakpoints_command, _("\
- Save current breakpoint definitions as a script.\n\
- This includes all types of breakpoints (breakpoints, watchpoints,\n\
- catchpoints, tracepoints). Use the 'source' command in another debug\n\
- session to restore them."),
- &save_cmdlist);
- set_cmd_completer (c, filename_completer);
- cmd_list_element *save_tracepoints_cmd
- = add_cmd ("tracepoints", class_trace, save_tracepoints_command, _("\
- Save current tracepoint definitions as a script.\n\
- Use the 'source' command in another debug session to restore them."),
- &save_cmdlist);
- set_cmd_completer (save_tracepoints_cmd, filename_completer);
- c = add_com_alias ("save-tracepoints", save_tracepoints_cmd, class_trace, 0);
- deprecate_cmd (c, "save tracepoints");
- add_setshow_prefix_cmd ("breakpoint", class_maintenance,
- _("\
- Breakpoint specific settings.\n\
- Configure various breakpoint-specific variables such as\n\
- pending breakpoint behavior."),
- _("\
- Breakpoint specific settings.\n\
- Configure various breakpoint-specific variables such as\n\
- pending breakpoint behavior."),
- &breakpoint_set_cmdlist, &breakpoint_show_cmdlist,
- &setlist, &showlist);
- add_setshow_auto_boolean_cmd ("pending", no_class,
- &pending_break_support, _("\
- Set debugger's behavior regarding pending breakpoints."), _("\
- Show debugger's behavior regarding pending breakpoints."), _("\
- If on, an unrecognized breakpoint location will cause gdb to create a\n\
- pending breakpoint. If off, an unrecognized breakpoint location results in\n\
- an error. If auto, an unrecognized breakpoint location results in a\n\
- user-query to see if a pending breakpoint should be created."),
- NULL,
- show_pending_break_support,
- &breakpoint_set_cmdlist,
- &breakpoint_show_cmdlist);
- pending_break_support = AUTO_BOOLEAN_AUTO;
- add_setshow_boolean_cmd ("auto-hw", no_class,
- &automatic_hardware_breakpoints, _("\
- Set automatic usage of hardware breakpoints."), _("\
- Show automatic usage of hardware breakpoints."), _("\
- If set, the debugger will automatically use hardware breakpoints for\n\
- breakpoints set with \"break\" but falling in read-only memory. If not set,\n\
- a warning will be emitted for such breakpoints."),
- NULL,
- show_automatic_hardware_breakpoints,
- &breakpoint_set_cmdlist,
- &breakpoint_show_cmdlist);
- add_setshow_boolean_cmd ("always-inserted", class_support,
- &always_inserted_mode, _("\
- Set mode for inserting breakpoints."), _("\
- Show mode for inserting breakpoints."), _("\
- When this mode is on, breakpoints are inserted immediately as soon as\n\
- they're created, kept inserted even when execution stops, and removed\n\
- only when the user deletes them. When this mode is off (the default),\n\
- breakpoints are inserted only when execution continues, and removed\n\
- when execution stops."),
- NULL,
- &show_always_inserted_mode,
- &breakpoint_set_cmdlist,
- &breakpoint_show_cmdlist);
- add_setshow_enum_cmd ("condition-evaluation", class_breakpoint,
- condition_evaluation_enums,
- &condition_evaluation_mode_1, _("\
- Set mode of breakpoint condition evaluation."), _("\
- Show mode of breakpoint condition evaluation."), _("\
- When this is set to \"host\", breakpoint conditions will be\n\
- evaluated on the host's side by GDB. When it is set to \"target\",\n\
- breakpoint conditions will be downloaded to the target (if the target\n\
- supports such feature) and conditions will be evaluated on the target's side.\n\
- If this is set to \"auto\" (default), this will be automatically set to\n\
- \"target\" if it supports condition evaluation, otherwise it will\n\
- be set to \"host\"."),
- &set_condition_evaluation_mode,
- &show_condition_evaluation_mode,
- &breakpoint_set_cmdlist,
- &breakpoint_show_cmdlist);
- add_com ("break-range", class_breakpoint, break_range_command, _("\
- Set a breakpoint for an address range.\n\
- break-range START-LOCATION, END-LOCATION\n\
- where START-LOCATION and END-LOCATION can be one of the following:\n\
- LINENUM, for that line in the current file,\n\
- FILE:LINENUM, for that line in that file,\n\
- +OFFSET, for that number of lines after the current line\n\
- or the start of the range\n\
- FUNCTION, for the first line in that function,\n\
- FILE:FUNCTION, to distinguish among like-named static functions.\n\
- *ADDRESS, for the instruction at that address.\n\
- \n\
- The breakpoint will stop execution of the inferior whenever it executes\n\
- an instruction at any address within the [START-LOCATION, END-LOCATION]\n\
- range (including START-LOCATION and END-LOCATION)."));
- c = add_com ("dprintf", class_breakpoint, dprintf_command, _("\
- Set a dynamic printf at specified location.\n\
- dprintf location,format string,arg1,arg2,...\n\
- location may be a linespec, explicit, or address location.\n"
- "\n" LOCATION_HELP_STRING));
- set_cmd_completer (c, location_completer);
- add_setshow_enum_cmd ("dprintf-style", class_support,
- dprintf_style_enums, &dprintf_style, _("\
- Set the style of usage for dynamic printf."), _("\
- Show the style of usage for dynamic printf."), _("\
- This setting chooses how GDB will do a dynamic printf.\n\
- If the value is \"gdb\", then the printing is done by GDB to its own\n\
- console, as with the \"printf\" command.\n\
- If the value is \"call\", the print is done by calling a function in your\n\
- program; by default printf(), but you can choose a different function or\n\
- output stream by setting dprintf-function and dprintf-channel."),
- update_dprintf_commands, NULL,
- &setlist, &showlist);
- add_setshow_string_cmd ("dprintf-function", class_support,
- &dprintf_function, _("\
- Set the function to use for dynamic printf."), _("\
- Show the function to use for dynamic printf."), NULL,
- update_dprintf_commands, NULL,
- &setlist, &showlist);
- add_setshow_string_cmd ("dprintf-channel", class_support,
- &dprintf_channel, _("\
- Set the channel to use for dynamic printf."), _("\
- Show the channel to use for dynamic printf."), NULL,
- update_dprintf_commands, NULL,
- &setlist, &showlist);
- add_setshow_boolean_cmd ("disconnected-dprintf", no_class,
- &disconnected_dprintf, _("\
- Set whether dprintf continues after GDB disconnects."), _("\
- Show whether dprintf continues after GDB disconnects."), _("\
- Use this to let dprintf commands continue to hit and produce output\n\
- even if GDB disconnects or detaches from the target."),
- NULL,
- NULL,
- &setlist, &showlist);
- add_com ("agent-printf", class_vars, agent_printf_command, _("\
- Target agent only formatted printing, like the C \"printf\" function.\n\
- Usage: agent-printf \"format string\", ARG1, ARG2, ARG3, ..., ARGN\n\
- This supports most C printf format specifications, like %s, %d, etc.\n\
- This is useful for formatted output in user-defined commands."));
- automatic_hardware_breakpoints = true;
- gdb::observers::about_to_proceed.attach (breakpoint_about_to_proceed,
- "breakpoint");
- gdb::observers::thread_exit.attach (remove_threaded_breakpoints,
- "breakpoint");
- }
|