12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233 |
- /* PPC GNU/Linux native support.
- Copyright (C) 1988-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 "frame.h"
- #include "inferior.h"
- #include "gdbthread.h"
- #include "gdbcore.h"
- #include "regcache.h"
- #include "regset.h"
- #include "target.h"
- #include "linux-nat.h"
- #include <sys/types.h>
- #include <signal.h>
- #include <sys/user.h>
- #include <sys/ioctl.h>
- #include <sys/uio.h>
- #include "gdbsupport/gdb_wait.h"
- #include <fcntl.h>
- #include <sys/procfs.h>
- #include "nat/gdb_ptrace.h"
- #include "nat/linux-ptrace.h"
- #include "inf-ptrace.h"
- #include <algorithm>
- #include <unordered_map>
- #include <list>
- /* Prototypes for supply_gregset etc. */
- #include "gregset.h"
- #include "ppc-tdep.h"
- #include "ppc-linux-tdep.h"
- /* Required when using the AUXV. */
- #include "elf/common.h"
- #include "auxv.h"
- #include "arch/ppc-linux-common.h"
- #include "arch/ppc-linux-tdesc.h"
- #include "nat/ppc-linux.h"
- #include "linux-tdep.h"
- #include "expop.h"
- /* Similarly for the hardware watchpoint support. These requests are used
- when the PowerPC HWDEBUG ptrace interface is not available. */
- #ifndef PTRACE_GET_DEBUGREG
- #define PTRACE_GET_DEBUGREG 25
- #endif
- #ifndef PTRACE_SET_DEBUGREG
- #define PTRACE_SET_DEBUGREG 26
- #endif
- #ifndef PTRACE_GETSIGINFO
- #define PTRACE_GETSIGINFO 0x4202
- #endif
- /* These requests are used when the PowerPC HWDEBUG ptrace interface is
- available. It exposes the debug facilities of PowerPC processors, as well
- as additional features of BookE processors, such as ranged breakpoints and
- watchpoints and hardware-accelerated condition evaluation. */
- #ifndef PPC_PTRACE_GETHWDBGINFO
- /* Not having PPC_PTRACE_GETHWDBGINFO defined means that the PowerPC HWDEBUG
- ptrace interface is not present in ptrace.h, so we'll have to pretty much
- include it all here so that the code at least compiles on older systems. */
- #define PPC_PTRACE_GETHWDBGINFO 0x89
- #define PPC_PTRACE_SETHWDEBUG 0x88
- #define PPC_PTRACE_DELHWDEBUG 0x87
- struct ppc_debug_info
- {
- uint32_t version; /* Only version 1 exists to date. */
- uint32_t num_instruction_bps;
- uint32_t num_data_bps;
- uint32_t num_condition_regs;
- uint32_t data_bp_alignment;
- uint32_t sizeof_condition; /* size of the DVC register. */
- uint64_t features;
- };
- /* Features will have bits indicating whether there is support for: */
- #define PPC_DEBUG_FEATURE_INSN_BP_RANGE 0x1
- #define PPC_DEBUG_FEATURE_INSN_BP_MASK 0x2
- #define PPC_DEBUG_FEATURE_DATA_BP_RANGE 0x4
- #define PPC_DEBUG_FEATURE_DATA_BP_MASK 0x8
- struct ppc_hw_breakpoint
- {
- uint32_t version; /* currently, version must be 1 */
- uint32_t trigger_type; /* only some combinations allowed */
- uint32_t addr_mode; /* address match mode */
- uint32_t condition_mode; /* break/watchpoint condition flags */
- uint64_t addr; /* break/watchpoint address */
- uint64_t addr2; /* range end or mask */
- uint64_t condition_value; /* contents of the DVC register */
- };
- /* Trigger type. */
- #define PPC_BREAKPOINT_TRIGGER_EXECUTE 0x1
- #define PPC_BREAKPOINT_TRIGGER_READ 0x2
- #define PPC_BREAKPOINT_TRIGGER_WRITE 0x4
- #define PPC_BREAKPOINT_TRIGGER_RW 0x6
- /* Address mode. */
- #define PPC_BREAKPOINT_MODE_EXACT 0x0
- #define PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE 0x1
- #define PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE 0x2
- #define PPC_BREAKPOINT_MODE_MASK 0x3
- /* Condition mode. */
- #define PPC_BREAKPOINT_CONDITION_NONE 0x0
- #define PPC_BREAKPOINT_CONDITION_AND 0x1
- #define PPC_BREAKPOINT_CONDITION_EXACT 0x1
- #define PPC_BREAKPOINT_CONDITION_OR 0x2
- #define PPC_BREAKPOINT_CONDITION_AND_OR 0x3
- #define PPC_BREAKPOINT_CONDITION_BE_ALL 0x00ff0000
- #define PPC_BREAKPOINT_CONDITION_BE_SHIFT 16
- #define PPC_BREAKPOINT_CONDITION_BE(n) \
- (1<<((n)+PPC_BREAKPOINT_CONDITION_BE_SHIFT))
- #endif /* PPC_PTRACE_GETHWDBGINFO */
- /* Feature defined on Linux kernel v3.9: DAWR interface, that enables wider
- watchpoint (up to 512 bytes). */
- #ifndef PPC_DEBUG_FEATURE_DATA_BP_DAWR
- #define PPC_DEBUG_FEATURE_DATA_BP_DAWR 0x10
- #endif /* PPC_DEBUG_FEATURE_DATA_BP_DAWR */
- /* Feature defined on Linux kernel v5.1: Second watchpoint support. */
- #ifndef PPC_DEBUG_FEATURE_DATA_BP_ARCH_31
- #define PPC_DEBUG_FEATURE_DATA_BP_ARCH_31 0x20
- #endif /* PPC_DEBUG_FEATURE_DATA_BP_ARCH_31 */
- /* The version of the PowerPC HWDEBUG kernel interface that we will use, if
- available. */
- #define PPC_DEBUG_CURRENT_VERSION 1
- /* Similarly for the general-purpose (gp0 -- gp31)
- and floating-point registers (fp0 -- fp31). */
- #ifndef PTRACE_GETREGS
- #define PTRACE_GETREGS 12
- #endif
- #ifndef PTRACE_SETREGS
- #define PTRACE_SETREGS 13
- #endif
- #ifndef PTRACE_GETFPREGS
- #define PTRACE_GETFPREGS 14
- #endif
- #ifndef PTRACE_SETFPREGS
- #define PTRACE_SETFPREGS 15
- #endif
- /* This oddity is because the Linux kernel defines elf_vrregset_t as
- an array of 33 16 bytes long elements. I.e. it leaves out vrsave.
- However the PTRACE_GETVRREGS and PTRACE_SETVRREGS requests return
- the vrsave as an extra 4 bytes at the end. I opted for creating a
- flat array of chars, so that it is easier to manipulate for gdb.
- There are 32 vector registers 16 bytes longs, plus a VSCR register
- which is only 4 bytes long, but is fetched as a 16 bytes
- quantity. Up to here we have the elf_vrregset_t structure.
- Appended to this there is space for the VRSAVE register: 4 bytes.
- Even though this vrsave register is not included in the regset
- typedef, it is handled by the ptrace requests.
- The layout is like this (where x is the actual value of the vscr reg): */
- /* *INDENT-OFF* */
- /*
- Big-Endian:
- |.|.|.|.|.....|.|.|.|.||.|.|.|x||.|
- <-------> <-------><-------><->
- VR0 VR31 VSCR VRSAVE
- Little-Endian:
- |.|.|.|.|.....|.|.|.|.||X|.|.|.||.|
- <-------> <-------><-------><->
- VR0 VR31 VSCR VRSAVE
- */
- /* *INDENT-ON* */
- typedef char gdb_vrregset_t[PPC_LINUX_SIZEOF_VRREGSET];
- /* This is the layout of the POWER7 VSX registers and the way they overlap
- with the existing FPR and VMX registers.
- VSR doubleword 0 VSR doubleword 1
- ----------------------------------------------------------------
- VSR[0] | FPR[0] | |
- ----------------------------------------------------------------
- VSR[1] | FPR[1] | |
- ----------------------------------------------------------------
- | ... | |
- | ... | |
- ----------------------------------------------------------------
- VSR[30] | FPR[30] | |
- ----------------------------------------------------------------
- VSR[31] | FPR[31] | |
- ----------------------------------------------------------------
- VSR[32] | VR[0] |
- ----------------------------------------------------------------
- VSR[33] | VR[1] |
- ----------------------------------------------------------------
- | ... |
- | ... |
- ----------------------------------------------------------------
- VSR[62] | VR[30] |
- ----------------------------------------------------------------
- VSR[63] | VR[31] |
- ----------------------------------------------------------------
- VSX has 64 128bit registers. The first 32 registers overlap with
- the FP registers (doubleword 0) and hence extend them with additional
- 64 bits (doubleword 1). The other 32 regs overlap with the VMX
- registers. */
- typedef char gdb_vsxregset_t[PPC_LINUX_SIZEOF_VSXREGSET];
- /* On PPC processors that support the Signal Processing Extension
- (SPE) APU, the general-purpose registers are 64 bits long.
- However, the ordinary Linux kernel PTRACE_PEEKUSER / PTRACE_POKEUSER
- ptrace calls only access the lower half of each register, to allow
- them to behave the same way they do on non-SPE systems. There's a
- separate pair of calls, PTRACE_GETEVRREGS / PTRACE_SETEVRREGS, that
- read and write the top halves of all the general-purpose registers
- at once, along with some SPE-specific registers.
- GDB itself continues to claim the general-purpose registers are 32
- bits long. It has unnamed raw registers that hold the upper halves
- of the gprs, and the full 64-bit SIMD views of the registers,
- 'ev0' -- 'ev31', are pseudo-registers that splice the top and
- bottom halves together.
- This is the structure filled in by PTRACE_GETEVRREGS and written to
- the inferior's registers by PTRACE_SETEVRREGS. */
- struct gdb_evrregset_t
- {
- unsigned long evr[32];
- unsigned long long acc;
- unsigned long spefscr;
- };
- /* Non-zero if our kernel may support the PTRACE_GETVSXREGS and
- PTRACE_SETVSXREGS requests, for reading and writing the VSX
- POWER7 registers 0 through 31. Zero if we've tried one of them and
- gotten an error. Note that VSX registers 32 through 63 overlap
- with VR registers 0 through 31. */
- int have_ptrace_getsetvsxregs = 1;
- /* Non-zero if our kernel may support the PTRACE_GETVRREGS and
- PTRACE_SETVRREGS requests, for reading and writing the Altivec
- registers. Zero if we've tried one of them and gotten an
- error. */
- int have_ptrace_getvrregs = 1;
- /* Non-zero if our kernel may support the PTRACE_GETEVRREGS and
- PTRACE_SETEVRREGS requests, for reading and writing the SPE
- registers. Zero if we've tried one of them and gotten an
- error. */
- int have_ptrace_getsetevrregs = 1;
- /* Non-zero if our kernel may support the PTRACE_GETREGS and
- PTRACE_SETREGS requests, for reading and writing the
- general-purpose registers. Zero if we've tried one of
- them and gotten an error. */
- int have_ptrace_getsetregs = 1;
- /* Non-zero if our kernel may support the PTRACE_GETFPREGS and
- PTRACE_SETFPREGS requests, for reading and writing the
- floating-pointers registers. Zero if we've tried one of
- them and gotten an error. */
- int have_ptrace_getsetfpregs = 1;
- /* Private arch info associated with each thread lwp_info object, used
- for debug register handling. */
- struct arch_lwp_info
- {
- /* When true, indicates that the debug registers installed in the
- thread no longer correspond to the watchpoints and breakpoints
- requested by GDB. */
- bool debug_regs_stale;
- /* We need a back-reference to the PTID of the thread so that we can
- cleanup the debug register state of the thread in
- low_delete_thread. */
- ptid_t lwp_ptid;
- };
- /* Class used to detect which set of ptrace requests that
- ppc_linux_nat_target will use to install and remove hardware
- breakpoints and watchpoints.
- The interface is only detected once, testing the ptrace calls. The
- result can indicate that no interface is available.
- The Linux kernel provides two different sets of ptrace requests to
- handle hardware watchpoints and breakpoints for Power:
- - PPC_PTRACE_GETHWDBGINFO, PPC_PTRACE_SETHWDEBUG, and
- PPC_PTRACE_DELHWDEBUG.
- Or
- - PTRACE_SET_DEBUGREG and PTRACE_GET_DEBUGREG
- The first set is the more flexible one and allows setting watchpoints
- with a variable watched region length and, for BookE processors,
- multiple types of debug registers (e.g. hardware breakpoints and
- hardware-assisted conditions for watchpoints). The second one only
- allows setting one debug register, a watchpoint, so we only use it if
- the first one is not available. */
- class ppc_linux_dreg_interface
- {
- public:
- ppc_linux_dreg_interface ()
- : m_interface (), m_hwdebug_info ()
- {
- };
- DISABLE_COPY_AND_ASSIGN (ppc_linux_dreg_interface);
- /* One and only one of these three functions returns true, indicating
- whether the corresponding interface is the one we detected. The
- interface must already have been detected as a precontidion. */
- bool hwdebug_p ()
- {
- gdb_assert (detected_p ());
- return *m_interface == HWDEBUG;
- }
- bool debugreg_p ()
- {
- gdb_assert (detected_p ());
- return *m_interface == DEBUGREG;
- }
- bool unavailable_p ()
- {
- gdb_assert (detected_p ());
- return *m_interface == UNAVAILABLE;
- }
- /* Returns the debug register capabilities of the target. Should only
- be called if the interface is HWDEBUG. */
- const struct ppc_debug_info &hwdebug_info ()
- {
- gdb_assert (hwdebug_p ());
- return m_hwdebug_info;
- }
- /* Returns true if the interface has already been detected. This is
- useful for cases when we know there is no work to be done if the
- interface hasn't been detected yet. */
- bool detected_p ()
- {
- return m_interface.has_value ();
- }
- /* Detect the available interface, if any, if it hasn't been detected
- before, using PTID for the necessary ptrace calls. */
- void detect (const ptid_t &ptid)
- {
- if (m_interface.has_value ())
- return;
- gdb_assert (ptid.lwp_p ());
- bool no_features = false;
- if (ptrace (PPC_PTRACE_GETHWDBGINFO, ptid.lwp (), 0, &m_hwdebug_info)
- >= 0)
- {
- /* If there are no advertised features, we don't use the
- HWDEBUG interface and try the DEBUGREG interface instead.
- It shouldn't be necessary to do this, however, when the
- kernel is configured without CONFIG_HW_BREAKPOINTS (selected
- by CONFIG_PERF_EVENTS), there is a bug that causes
- watchpoints installed with the HWDEBUG interface not to
- trigger. When this is the case, features will be zero,
- which we use as an indicator to fall back to the DEBUGREG
- interface. */
- if (m_hwdebug_info.features != 0)
- {
- m_interface.emplace (HWDEBUG);
- return;
- }
- else
- no_features = true;
- }
- /* EIO indicates that the request is invalid, so we try DEBUGREG
- next. Technically, it can also indicate other failures, but we
- can't differentiate those.
- Other errors could happen for various reasons. We could get an
- ESRCH if the traced thread was killed by a signal. Trying to
- detect the interface with another thread in the future would be
- complicated, as callers would have to handle an "unknown
- interface" case. It's also unclear if raising an exception
- here would be safe.
- Other errors, such as ENODEV, could be more permanent and cause
- a failure for any thread.
- For simplicity, with all errors other than EIO, we set the
- interface to UNAVAILABLE and don't try DEBUGREG. If DEBUGREG
- fails too, we'll also set the interface to UNAVAILABLE. It's
- unlikely that trying the DEBUGREG interface with this same thread
- would work, for errors other than EIO. This means that these
- errors will cause hardware watchpoints and breakpoints to become
- unavailable throughout a GDB session. */
- if (no_features || errno == EIO)
- {
- unsigned long wp;
- if (ptrace (PTRACE_GET_DEBUGREG, ptid.lwp (), 0, &wp) >= 0)
- {
- m_interface.emplace (DEBUGREG);
- return;
- }
- }
- if (errno != EIO)
- warning (_("Error when detecting the debug register interface. "
- "Debug registers will be unavailable."));
- m_interface.emplace (UNAVAILABLE);
- return;
- }
- private:
- /* HWDEBUG represents the set of calls PPC_PTRACE_GETHWDBGINFO,
- PPC_PTRACE_SETHWDEBUG and PPC_PTRACE_DELHWDEBUG.
- DEBUGREG represents the set of calls PTRACE_SET_DEBUGREG and
- PTRACE_GET_DEBUGREG.
- UNAVAILABLE can indicate that the kernel doesn't support any of the
- two sets of requests or that there was an error when we tried to
- detect wich interface is available. */
- enum debug_reg_interface
- {
- UNAVAILABLE,
- HWDEBUG,
- DEBUGREG
- };
- /* The interface option. Initialized if has_value () returns true. */
- gdb::optional<enum debug_reg_interface> m_interface;
- /* The info returned by the kernel with PPC_PTRACE_GETHWDBGINFO. Only
- valid if we determined that the interface is HWDEBUG. */
- struct ppc_debug_info m_hwdebug_info;
- };
- /* Per-process information. This includes the hardware watchpoints and
- breakpoints that GDB requested to this target. */
- struct ppc_linux_process_info
- {
- /* The list of hardware watchpoints and breakpoints that GDB requested
- for this process.
- Only used when the interface is HWDEBUG. */
- std::list<struct ppc_hw_breakpoint> requested_hw_bps;
- /* The watchpoint value that GDB requested for this process.
- Only used when the interface is DEBUGREG. */
- gdb::optional<long> requested_wp_val;
- };
- struct ppc_linux_nat_target final : public linux_nat_target
- {
- /* Add our register access methods. */
- void fetch_registers (struct regcache *, int) override;
- void store_registers (struct regcache *, int) override;
- /* Add our breakpoint/watchpoint methods. */
- int can_use_hw_breakpoint (enum bptype, int, int) override;
- int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *)
- override;
- int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *)
- override;
- int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
- int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
- struct expression *) override;
- int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
- struct expression *) override;
- int insert_mask_watchpoint (CORE_ADDR, CORE_ADDR, enum target_hw_bp_type)
- override;
- int remove_mask_watchpoint (CORE_ADDR, CORE_ADDR, enum target_hw_bp_type)
- override;
- bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
- bool can_accel_watchpoint_condition (CORE_ADDR, int, int, struct expression *)
- override;
- int masked_watch_num_registers (CORE_ADDR, CORE_ADDR) override;
- int ranged_break_num_registers () override;
- const struct target_desc *read_description () override;
- int auxv_parse (gdb_byte **readptr,
- gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
- override;
- /* Override linux_nat_target low methods. */
- bool low_stopped_by_watchpoint () override;
- bool low_stopped_data_address (CORE_ADDR *) override;
- void low_new_thread (struct lwp_info *lp) override;
- void low_delete_thread (arch_lwp_info *) override;
- void low_new_fork (struct lwp_info *, pid_t) override;
- void low_new_clone (struct lwp_info *, pid_t) override;
- void low_forget_process (pid_t pid) override;
- void low_prepare_to_resume (struct lwp_info *) override;
- private:
- void copy_thread_dreg_state (const ptid_t &parent_ptid,
- const ptid_t &child_ptid);
- void mark_thread_stale (struct lwp_info *lp);
- void mark_debug_registers_changed (pid_t pid);
- void register_hw_breakpoint (pid_t pid,
- const struct ppc_hw_breakpoint &bp);
- void clear_hw_breakpoint (pid_t pid,
- const struct ppc_hw_breakpoint &a);
- void register_wp (pid_t pid, long wp_value);
- void clear_wp (pid_t pid);
- bool can_use_watchpoint_cond_accel (void);
- void calculate_dvc (CORE_ADDR addr, int len,
- CORE_ADDR data_value,
- uint32_t *condition_mode,
- uint64_t *condition_value);
- int check_condition (CORE_ADDR watch_addr,
- struct expression *cond,
- CORE_ADDR *data_value, int *len);
- int num_memory_accesses (const std::vector<value_ref_ptr> &chain);
- int get_trigger_type (enum target_hw_bp_type type);
- void create_watchpoint_request (struct ppc_hw_breakpoint *p,
- CORE_ADDR addr,
- int len,
- enum target_hw_bp_type type,
- struct expression *cond,
- int insert);
- bool hwdebug_point_cmp (const struct ppc_hw_breakpoint &a,
- const struct ppc_hw_breakpoint &b);
- void init_arch_lwp_info (struct lwp_info *lp);
- arch_lwp_info *get_arch_lwp_info (struct lwp_info *lp);
- /* The ptrace interface we'll use to install hardware watchpoints and
- breakpoints (debug registers). */
- ppc_linux_dreg_interface m_dreg_interface;
- /* A map from pids to structs containing info specific to each
- process. */
- std::unordered_map<pid_t, ppc_linux_process_info> m_process_info;
- /* Callable object to hash ptids by their lwp number. */
- struct ptid_hash
- {
- std::size_t operator() (const ptid_t &ptid) const
- {
- return std::hash<long>{} (ptid.lwp ());
- }
- };
- /* A map from ptid_t objects to a list of pairs of slots and hardware
- breakpoint objects. This keeps track of which hardware breakpoints
- and watchpoints were last installed in each slot of each thread.
- Only used when the interface is HWDEBUG. */
- std::unordered_map <ptid_t,
- std::list<std::pair<long, ppc_hw_breakpoint>>,
- ptid_hash> m_installed_hw_bps;
- };
- static ppc_linux_nat_target the_ppc_linux_nat_target;
- /* *INDENT-OFF* */
- /* registers layout, as presented by the ptrace interface:
- PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
- PT_R8, PT_R9, PT_R10, PT_R11, PT_R12, PT_R13, PT_R14, PT_R15,
- PT_R16, PT_R17, PT_R18, PT_R19, PT_R20, PT_R21, PT_R22, PT_R23,
- PT_R24, PT_R25, PT_R26, PT_R27, PT_R28, PT_R29, PT_R30, PT_R31,
- PT_FPR0, PT_FPR0 + 2, PT_FPR0 + 4, PT_FPR0 + 6,
- PT_FPR0 + 8, PT_FPR0 + 10, PT_FPR0 + 12, PT_FPR0 + 14,
- PT_FPR0 + 16, PT_FPR0 + 18, PT_FPR0 + 20, PT_FPR0 + 22,
- PT_FPR0 + 24, PT_FPR0 + 26, PT_FPR0 + 28, PT_FPR0 + 30,
- PT_FPR0 + 32, PT_FPR0 + 34, PT_FPR0 + 36, PT_FPR0 + 38,
- PT_FPR0 + 40, PT_FPR0 + 42, PT_FPR0 + 44, PT_FPR0 + 46,
- PT_FPR0 + 48, PT_FPR0 + 50, PT_FPR0 + 52, PT_FPR0 + 54,
- PT_FPR0 + 56, PT_FPR0 + 58, PT_FPR0 + 60, PT_FPR0 + 62,
- PT_NIP, PT_MSR, PT_CCR, PT_LNK, PT_CTR, PT_XER, PT_MQ */
- /* *INDENT_ON * */
- static int
- ppc_register_u_addr (struct gdbarch *gdbarch, int regno)
- {
- int u_addr = -1;
- ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace
- interface, and not the wordsize of the program's ABI. */
- int wordsize = sizeof (long);
- /* General purpose registers occupy 1 slot each in the buffer. */
- if (regno >= tdep->ppc_gp0_regnum
- && regno < tdep->ppc_gp0_regnum + ppc_num_gprs)
- u_addr = ((regno - tdep->ppc_gp0_regnum + PT_R0) * wordsize);
- /* Floating point regs: eight bytes each in both 32- and 64-bit
- ptrace interfaces. Thus, two slots each in 32-bit interface, one
- slot each in 64-bit interface. */
- if (tdep->ppc_fp0_regnum >= 0
- && regno >= tdep->ppc_fp0_regnum
- && regno < tdep->ppc_fp0_regnum + ppc_num_fprs)
- u_addr = (PT_FPR0 * wordsize) + ((regno - tdep->ppc_fp0_regnum) * 8);
- /* UISA special purpose registers: 1 slot each. */
- if (regno == gdbarch_pc_regnum (gdbarch))
- u_addr = PT_NIP * wordsize;
- if (regno == tdep->ppc_lr_regnum)
- u_addr = PT_LNK * wordsize;
- if (regno == tdep->ppc_cr_regnum)
- u_addr = PT_CCR * wordsize;
- if (regno == tdep->ppc_xer_regnum)
- u_addr = PT_XER * wordsize;
- if (regno == tdep->ppc_ctr_regnum)
- u_addr = PT_CTR * wordsize;
- #ifdef PT_MQ
- if (regno == tdep->ppc_mq_regnum)
- u_addr = PT_MQ * wordsize;
- #endif
- if (regno == tdep->ppc_ps_regnum)
- u_addr = PT_MSR * wordsize;
- if (regno == PPC_ORIG_R3_REGNUM)
- u_addr = PT_ORIG_R3 * wordsize;
- if (regno == PPC_TRAP_REGNUM)
- u_addr = PT_TRAP * wordsize;
- if (tdep->ppc_fpscr_regnum >= 0
- && regno == tdep->ppc_fpscr_regnum)
- {
- /* NOTE: cagney/2005-02-08: On some 64-bit GNU/Linux systems the
- kernel headers incorrectly contained the 32-bit definition of
- PT_FPSCR. For the 32-bit definition, floating-point
- registers occupy two 32-bit "slots", and the FPSCR lives in
- the second half of such a slot-pair (hence +1). For 64-bit,
- the FPSCR instead occupies the full 64-bit 2-word-slot and
- hence no adjustment is necessary. Hack around this. */
- if (wordsize == 8 && PT_FPSCR == (48 + 32 + 1))
- u_addr = (48 + 32) * wordsize;
- /* If the FPSCR is 64-bit wide, we need to fetch the whole 64-bit
- slot and not just its second word. The PT_FPSCR supplied when
- GDB is compiled as a 32-bit app doesn't reflect this. */
- else if (wordsize == 4 && register_size (gdbarch, regno) == 8
- && PT_FPSCR == (48 + 2*32 + 1))
- u_addr = (48 + 2*32) * wordsize;
- else
- u_addr = PT_FPSCR * wordsize;
- }
- return u_addr;
- }
- /* The Linux kernel ptrace interface for POWER7 VSX registers uses the
- registers set mechanism, as opposed to the interface for all the
- other registers, that stores/fetches each register individually. */
- static void
- fetch_vsx_registers (struct regcache *regcache, int tid, int regno)
- {
- int ret;
- gdb_vsxregset_t regs;
- const struct regset *vsxregset = ppc_linux_vsxregset ();
- ret = ptrace (PTRACE_GETVSXREGS, tid, 0, ®s);
- if (ret < 0)
- {
- if (errno == EIO)
- {
- have_ptrace_getsetvsxregs = 0;
- return;
- }
- perror_with_name (_("Unable to fetch VSX registers"));
- }
- vsxregset->supply_regset (vsxregset, regcache, regno, ®s,
- PPC_LINUX_SIZEOF_VSXREGSET);
- }
- /* The Linux kernel ptrace interface for AltiVec registers uses the
- registers set mechanism, as opposed to the interface for all the
- other registers, that stores/fetches each register individually. */
- static void
- fetch_altivec_registers (struct regcache *regcache, int tid,
- int regno)
- {
- int ret;
- gdb_vrregset_t regs;
- struct gdbarch *gdbarch = regcache->arch ();
- const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
- ret = ptrace (PTRACE_GETVRREGS, tid, 0, ®s);
- if (ret < 0)
- {
- if (errno == EIO)
- {
- have_ptrace_getvrregs = 0;
- return;
- }
- perror_with_name (_("Unable to fetch AltiVec registers"));
- }
- vrregset->supply_regset (vrregset, regcache, regno, ®s,
- PPC_LINUX_SIZEOF_VRREGSET);
- }
- /* Fetch the top 32 bits of TID's general-purpose registers and the
- SPE-specific registers, and place the results in EVRREGSET. If we
- don't support PTRACE_GETEVRREGS, then just fill EVRREGSET with
- zeros.
- All the logic to deal with whether or not the PTRACE_GETEVRREGS and
- PTRACE_SETEVRREGS requests are supported is isolated here, and in
- set_spe_registers. */
- static void
- get_spe_registers (int tid, struct gdb_evrregset_t *evrregset)
- {
- if (have_ptrace_getsetevrregs)
- {
- if (ptrace (PTRACE_GETEVRREGS, tid, 0, evrregset) >= 0)
- return;
- else
- {
- /* EIO means that the PTRACE_GETEVRREGS request isn't supported;
- we just return zeros. */
- if (errno == EIO)
- have_ptrace_getsetevrregs = 0;
- else
- /* Anything else needs to be reported. */
- perror_with_name (_("Unable to fetch SPE registers"));
- }
- }
- memset (evrregset, 0, sizeof (*evrregset));
- }
- /* Supply values from TID for SPE-specific raw registers: the upper
- halves of the GPRs, the accumulator, and the spefscr. REGNO must
- be the number of an upper half register, acc, spefscr, or -1 to
- supply the values of all registers. */
- static void
- fetch_spe_register (struct regcache *regcache, int tid, int regno)
- {
- struct gdbarch *gdbarch = regcache->arch ();
- ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- struct gdb_evrregset_t evrregs;
- gdb_assert (sizeof (evrregs.evr[0])
- == register_size (gdbarch, tdep->ppc_ev0_upper_regnum));
- gdb_assert (sizeof (evrregs.acc)
- == register_size (gdbarch, tdep->ppc_acc_regnum));
- gdb_assert (sizeof (evrregs.spefscr)
- == register_size (gdbarch, tdep->ppc_spefscr_regnum));
- get_spe_registers (tid, &evrregs);
- if (regno == -1)
- {
- int i;
- for (i = 0; i < ppc_num_gprs; i++)
- regcache->raw_supply (tdep->ppc_ev0_upper_regnum + i, &evrregs.evr[i]);
- }
- else if (tdep->ppc_ev0_upper_regnum <= regno
- && regno < tdep->ppc_ev0_upper_regnum + ppc_num_gprs)
- regcache->raw_supply (regno,
- &evrregs.evr[regno - tdep->ppc_ev0_upper_regnum]);
- if (regno == -1
- || regno == tdep->ppc_acc_regnum)
- regcache->raw_supply (tdep->ppc_acc_regnum, &evrregs.acc);
- if (regno == -1
- || regno == tdep->ppc_spefscr_regnum)
- regcache->raw_supply (tdep->ppc_spefscr_regnum, &evrregs.spefscr);
- }
- /* Use ptrace to fetch all registers from the register set with note
- type REGSET_ID, size REGSIZE, and layout described by REGSET, from
- process/thread TID and supply their values to REGCACHE. If ptrace
- returns ENODATA to indicate the regset is unavailable, mark the
- registers as unavailable in REGCACHE. */
- static void
- fetch_regset (struct regcache *regcache, int tid,
- int regset_id, int regsetsize, const struct regset *regset)
- {
- void *buf = alloca (regsetsize);
- struct iovec iov;
- iov.iov_base = buf;
- iov.iov_len = regsetsize;
- if (ptrace (PTRACE_GETREGSET, tid, regset_id, &iov) < 0)
- {
- if (errno == ENODATA)
- regset->supply_regset (regset, regcache, -1, NULL, regsetsize);
- else
- perror_with_name (_("Couldn't get register set"));
- }
- else
- regset->supply_regset (regset, regcache, -1, buf, regsetsize);
- }
- /* Use ptrace to store register REGNUM of the regset with note type
- REGSET_ID, size REGSETSIZE, and layout described by REGSET, from
- REGCACHE back to process/thread TID. If REGNUM is -1 all registers
- in the set are collected and stored. */
- static void
- store_regset (const struct regcache *regcache, int tid, int regnum,
- int regset_id, int regsetsize, const struct regset *regset)
- {
- void *buf = alloca (regsetsize);
- struct iovec iov;
- iov.iov_base = buf;
- iov.iov_len = regsetsize;
- /* Make sure that the buffer that will be stored has up to date values
- for the registers that won't be collected. */
- if (ptrace (PTRACE_GETREGSET, tid, regset_id, &iov) < 0)
- perror_with_name (_("Couldn't get register set"));
- regset->collect_regset (regset, regcache, regnum, buf, regsetsize);
- if (ptrace (PTRACE_SETREGSET, tid, regset_id, &iov) < 0)
- perror_with_name (_("Couldn't set register set"));
- }
- /* Check whether the kernel provides a register set with number
- REGSET_ID of size REGSETSIZE for process/thread TID. */
- static bool
- check_regset (int tid, int regset_id, int regsetsize)
- {
- void *buf = alloca (regsetsize);
- struct iovec iov;
- iov.iov_base = buf;
- iov.iov_len = regsetsize;
- if (ptrace (PTRACE_GETREGSET, tid, regset_id, &iov) >= 0
- || errno == ENODATA)
- return true;
- else
- return false;
- }
- static void
- fetch_register (struct regcache *regcache, int tid, int regno)
- {
- struct gdbarch *gdbarch = regcache->arch ();
- ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- /* This isn't really an address. But ptrace thinks of it as one. */
- CORE_ADDR regaddr = ppc_register_u_addr (gdbarch, regno);
- int bytes_transferred;
- gdb_byte buf[PPC_MAX_REGISTER_SIZE];
- if (altivec_register_p (gdbarch, regno))
- {
- /* If this is the first time through, or if it is not the first
- time through, and we have confirmed that there is kernel
- support for such a ptrace request, then go and fetch the
- register. */
- if (have_ptrace_getvrregs)
- {
- fetch_altivec_registers (regcache, tid, regno);
- return;
- }
- /* If we have discovered that there is no ptrace support for
- AltiVec registers, fall through and return zeroes, because
- regaddr will be -1 in this case. */
- }
- else if (vsx_register_p (gdbarch, regno))
- {
- if (have_ptrace_getsetvsxregs)
- {
- fetch_vsx_registers (regcache, tid, regno);
- return;
- }
- }
- else if (spe_register_p (gdbarch, regno))
- {
- fetch_spe_register (regcache, tid, regno);
- return;
- }
- else if (regno == PPC_DSCR_REGNUM)
- {
- gdb_assert (tdep->ppc_dscr_regnum != -1);
- fetch_regset (regcache, tid, NT_PPC_DSCR,
- PPC_LINUX_SIZEOF_DSCRREGSET,
- &ppc32_linux_dscrregset);
- return;
- }
- else if (regno == PPC_PPR_REGNUM)
- {
- gdb_assert (tdep->ppc_ppr_regnum != -1);
- fetch_regset (regcache, tid, NT_PPC_PPR,
- PPC_LINUX_SIZEOF_PPRREGSET,
- &ppc32_linux_pprregset);
- return;
- }
- else if (regno == PPC_TAR_REGNUM)
- {
- gdb_assert (tdep->ppc_tar_regnum != -1);
- fetch_regset (regcache, tid, NT_PPC_TAR,
- PPC_LINUX_SIZEOF_TARREGSET,
- &ppc32_linux_tarregset);
- return;
- }
- else if (PPC_IS_EBB_REGNUM (regno))
- {
- gdb_assert (tdep->have_ebb);
- fetch_regset (regcache, tid, NT_PPC_EBB,
- PPC_LINUX_SIZEOF_EBBREGSET,
- &ppc32_linux_ebbregset);
- return;
- }
- else if (PPC_IS_PMU_REGNUM (regno))
- {
- gdb_assert (tdep->ppc_mmcr0_regnum != -1);
- fetch_regset (regcache, tid, NT_PPC_PMU,
- PPC_LINUX_SIZEOF_PMUREGSET,
- &ppc32_linux_pmuregset);
- return;
- }
- else if (PPC_IS_TMSPR_REGNUM (regno))
- {
- gdb_assert (tdep->have_htm_spr);
- fetch_regset (regcache, tid, NT_PPC_TM_SPR,
- PPC_LINUX_SIZEOF_TM_SPRREGSET,
- &ppc32_linux_tm_sprregset);
- return;
- }
- else if (PPC_IS_CKPTGP_REGNUM (regno))
- {
- gdb_assert (tdep->have_htm_core);
- const struct regset *cgprregset = ppc_linux_cgprregset (gdbarch);
- fetch_regset (regcache, tid, NT_PPC_TM_CGPR,
- (tdep->wordsize == 4?
- PPC32_LINUX_SIZEOF_CGPRREGSET
- : PPC64_LINUX_SIZEOF_CGPRREGSET),
- cgprregset);
- return;
- }
- else if (PPC_IS_CKPTFP_REGNUM (regno))
- {
- gdb_assert (tdep->have_htm_fpu);
- fetch_regset (regcache, tid, NT_PPC_TM_CFPR,
- PPC_LINUX_SIZEOF_CFPRREGSET,
- &ppc32_linux_cfprregset);
- return;
- }
- else if (PPC_IS_CKPTVMX_REGNUM (regno))
- {
- gdb_assert (tdep->have_htm_altivec);
- const struct regset *cvmxregset = ppc_linux_cvmxregset (gdbarch);
- fetch_regset (regcache, tid, NT_PPC_TM_CVMX,
- PPC_LINUX_SIZEOF_CVMXREGSET,
- cvmxregset);
- return;
- }
- else if (PPC_IS_CKPTVSX_REGNUM (regno))
- {
- gdb_assert (tdep->have_htm_vsx);
- fetch_regset (regcache, tid, NT_PPC_TM_CVSX,
- PPC_LINUX_SIZEOF_CVSXREGSET,
- &ppc32_linux_cvsxregset);
- return;
- }
- else if (regno == PPC_CPPR_REGNUM)
- {
- gdb_assert (tdep->ppc_cppr_regnum != -1);
- fetch_regset (regcache, tid, NT_PPC_TM_CPPR,
- PPC_LINUX_SIZEOF_CPPRREGSET,
- &ppc32_linux_cpprregset);
- return;
- }
- else if (regno == PPC_CDSCR_REGNUM)
- {
- gdb_assert (tdep->ppc_cdscr_regnum != -1);
- fetch_regset (regcache, tid, NT_PPC_TM_CDSCR,
- PPC_LINUX_SIZEOF_CDSCRREGSET,
- &ppc32_linux_cdscrregset);
- return;
- }
- else if (regno == PPC_CTAR_REGNUM)
- {
- gdb_assert (tdep->ppc_ctar_regnum != -1);
- fetch_regset (regcache, tid, NT_PPC_TM_CTAR,
- PPC_LINUX_SIZEOF_CTARREGSET,
- &ppc32_linux_ctarregset);
- return;
- }
- if (regaddr == -1)
- {
- memset (buf, '\0', register_size (gdbarch, regno)); /* Supply zeroes */
- regcache->raw_supply (regno, buf);
- return;
- }
- /* Read the raw register using sizeof(long) sized chunks. On a
- 32-bit platform, 64-bit floating-point registers will require two
- transfers. */
- for (bytes_transferred = 0;
- bytes_transferred < register_size (gdbarch, regno);
- bytes_transferred += sizeof (long))
- {
- long l;
- errno = 0;
- l = ptrace (PTRACE_PEEKUSER, tid, (PTRACE_TYPE_ARG3) regaddr, 0);
- regaddr += sizeof (long);
- if (errno != 0)
- {
- char message[128];
- xsnprintf (message, sizeof (message), "reading register %s (#%d)",
- gdbarch_register_name (gdbarch, regno), regno);
- perror_with_name (message);
- }
- memcpy (&buf[bytes_transferred], &l, sizeof (l));
- }
- /* Now supply the register. Keep in mind that the regcache's idea
- of the register's size may not be a multiple of sizeof
- (long). */
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
- {
- /* Little-endian values are always found at the left end of the
- bytes transferred. */
- regcache->raw_supply (regno, buf);
- }
- else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- {
- /* Big-endian values are found at the right end of the bytes
- transferred. */
- size_t padding = (bytes_transferred - register_size (gdbarch, regno));
- regcache->raw_supply (regno, buf + padding);
- }
- else
- internal_error (__FILE__, __LINE__,
- _("fetch_register: unexpected byte order: %d"),
- gdbarch_byte_order (gdbarch));
- }
- /* This function actually issues the request to ptrace, telling
- it to get all general-purpose registers and put them into the
- specified regset.
-
- If the ptrace request does not exist, this function returns 0
- and properly sets the have_ptrace_* flag. If the request fails,
- this function calls perror_with_name. Otherwise, if the request
- succeeds, then the regcache gets filled and 1 is returned. */
- static int
- fetch_all_gp_regs (struct regcache *regcache, int tid)
- {
- gdb_gregset_t gregset;
- if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0)
- {
- if (errno == EIO)
- {
- have_ptrace_getsetregs = 0;
- return 0;
- }
- perror_with_name (_("Couldn't get general-purpose registers."));
- }
- supply_gregset (regcache, (const gdb_gregset_t *) &gregset);
- return 1;
- }
- /* This is a wrapper for the fetch_all_gp_regs function. It is
- responsible for verifying if this target has the ptrace request
- that can be used to fetch all general-purpose registers at one
- shot. If it doesn't, then we should fetch them using the
- old-fashioned way, which is to iterate over the registers and
- request them one by one. */
- static void
- fetch_gp_regs (struct regcache *regcache, int tid)
- {
- struct gdbarch *gdbarch = regcache->arch ();
- ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- int i;
- if (have_ptrace_getsetregs)
- if (fetch_all_gp_regs (regcache, tid))
- return;
- /* If we've hit this point, it doesn't really matter which
- architecture we are using. We just need to read the
- registers in the "old-fashioned way". */
- for (i = 0; i < ppc_num_gprs; i++)
- fetch_register (regcache, tid, tdep->ppc_gp0_regnum + i);
- }
- /* This function actually issues the request to ptrace, telling
- it to get all floating-point registers and put them into the
- specified regset.
-
- If the ptrace request does not exist, this function returns 0
- and properly sets the have_ptrace_* flag. If the request fails,
- this function calls perror_with_name. Otherwise, if the request
- succeeds, then the regcache gets filled and 1 is returned. */
- static int
- fetch_all_fp_regs (struct regcache *regcache, int tid)
- {
- gdb_fpregset_t fpregs;
- if (ptrace (PTRACE_GETFPREGS, tid, 0, (void *) &fpregs) < 0)
- {
- if (errno == EIO)
- {
- have_ptrace_getsetfpregs = 0;
- return 0;
- }
- perror_with_name (_("Couldn't get floating-point registers."));
- }
- supply_fpregset (regcache, (const gdb_fpregset_t *) &fpregs);
- return 1;
- }
- /* This is a wrapper for the fetch_all_fp_regs function. It is
- responsible for verifying if this target has the ptrace request
- that can be used to fetch all floating-point registers at one
- shot. If it doesn't, then we should fetch them using the
- old-fashioned way, which is to iterate over the registers and
- request them one by one. */
- static void
- fetch_fp_regs (struct regcache *regcache, int tid)
- {
- struct gdbarch *gdbarch = regcache->arch ();
- ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- int i;
- if (have_ptrace_getsetfpregs)
- if (fetch_all_fp_regs (regcache, tid))
- return;
-
- /* If we've hit this point, it doesn't really matter which
- architecture we are using. We just need to read the
- registers in the "old-fashioned way". */
- for (i = 0; i < ppc_num_fprs; i++)
- fetch_register (regcache, tid, tdep->ppc_fp0_regnum + i);
- }
- static void
- fetch_ppc_registers (struct regcache *regcache, int tid)
- {
- struct gdbarch *gdbarch = regcache->arch ();
- ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- fetch_gp_regs (regcache, tid);
- if (tdep->ppc_fp0_regnum >= 0)
- fetch_fp_regs (regcache, tid);
- fetch_register (regcache, tid, gdbarch_pc_regnum (gdbarch));
- if (tdep->ppc_ps_regnum != -1)
- fetch_register (regcache, tid, tdep->ppc_ps_regnum);
- if (tdep->ppc_cr_regnum != -1)
- fetch_register (regcache, tid, tdep->ppc_cr_regnum);
- if (tdep->ppc_lr_regnum != -1)
- fetch_register (regcache, tid, tdep->ppc_lr_regnum);
- if (tdep->ppc_ctr_regnum != -1)
- fetch_register (regcache, tid, tdep->ppc_ctr_regnum);
- if (tdep->ppc_xer_regnum != -1)
- fetch_register (regcache, tid, tdep->ppc_xer_regnum);
- if (tdep->ppc_mq_regnum != -1)
- fetch_register (regcache, tid, tdep->ppc_mq_regnum);
- if (ppc_linux_trap_reg_p (gdbarch))
- {
- fetch_register (regcache, tid, PPC_ORIG_R3_REGNUM);
- fetch_register (regcache, tid, PPC_TRAP_REGNUM);
- }
- if (tdep->ppc_fpscr_regnum != -1)
- fetch_register (regcache, tid, tdep->ppc_fpscr_regnum);
- if (have_ptrace_getvrregs)
- if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
- fetch_altivec_registers (regcache, tid, -1);
- if (have_ptrace_getsetvsxregs)
- if (tdep->ppc_vsr0_upper_regnum != -1)
- fetch_vsx_registers (regcache, tid, -1);
- if (tdep->ppc_ev0_upper_regnum >= 0)
- fetch_spe_register (regcache, tid, -1);
- if (tdep->ppc_ppr_regnum != -1)
- fetch_regset (regcache, tid, NT_PPC_PPR,
- PPC_LINUX_SIZEOF_PPRREGSET,
- &ppc32_linux_pprregset);
- if (tdep->ppc_dscr_regnum != -1)
- fetch_regset (regcache, tid, NT_PPC_DSCR,
- PPC_LINUX_SIZEOF_DSCRREGSET,
- &ppc32_linux_dscrregset);
- if (tdep->ppc_tar_regnum != -1)
- fetch_regset (regcache, tid, NT_PPC_TAR,
- PPC_LINUX_SIZEOF_TARREGSET,
- &ppc32_linux_tarregset);
- if (tdep->have_ebb)
- fetch_regset (regcache, tid, NT_PPC_EBB,
- PPC_LINUX_SIZEOF_EBBREGSET,
- &ppc32_linux_ebbregset);
- if (tdep->ppc_mmcr0_regnum != -1)
- fetch_regset (regcache, tid, NT_PPC_PMU,
- PPC_LINUX_SIZEOF_PMUREGSET,
- &ppc32_linux_pmuregset);
- if (tdep->have_htm_spr)
- fetch_regset (regcache, tid, NT_PPC_TM_SPR,
- PPC_LINUX_SIZEOF_TM_SPRREGSET,
- &ppc32_linux_tm_sprregset);
- if (tdep->have_htm_core)
- {
- const struct regset *cgprregset = ppc_linux_cgprregset (gdbarch);
- fetch_regset (regcache, tid, NT_PPC_TM_CGPR,
- (tdep->wordsize == 4?
- PPC32_LINUX_SIZEOF_CGPRREGSET
- : PPC64_LINUX_SIZEOF_CGPRREGSET),
- cgprregset);
- }
- if (tdep->have_htm_fpu)
- fetch_regset (regcache, tid, NT_PPC_TM_CFPR,
- PPC_LINUX_SIZEOF_CFPRREGSET,
- &ppc32_linux_cfprregset);
- if (tdep->have_htm_altivec)
- {
- const struct regset *cvmxregset = ppc_linux_cvmxregset (gdbarch);
- fetch_regset (regcache, tid, NT_PPC_TM_CVMX,
- PPC_LINUX_SIZEOF_CVMXREGSET,
- cvmxregset);
- }
- if (tdep->have_htm_vsx)
- fetch_regset (regcache, tid, NT_PPC_TM_CVSX,
- PPC_LINUX_SIZEOF_CVSXREGSET,
- &ppc32_linux_cvsxregset);
- if (tdep->ppc_cppr_regnum != -1)
- fetch_regset (regcache, tid, NT_PPC_TM_CPPR,
- PPC_LINUX_SIZEOF_CPPRREGSET,
- &ppc32_linux_cpprregset);
- if (tdep->ppc_cdscr_regnum != -1)
- fetch_regset (regcache, tid, NT_PPC_TM_CDSCR,
- PPC_LINUX_SIZEOF_CDSCRREGSET,
- &ppc32_linux_cdscrregset);
- if (tdep->ppc_ctar_regnum != -1)
- fetch_regset (regcache, tid, NT_PPC_TM_CTAR,
- PPC_LINUX_SIZEOF_CTARREGSET,
- &ppc32_linux_ctarregset);
- }
- /* Fetch registers from the child process. Fetch all registers if
- regno == -1, otherwise fetch all general registers or all floating
- point registers depending upon the value of regno. */
- void
- ppc_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
- {
- pid_t tid = get_ptrace_pid (regcache->ptid ());
- if (regno == -1)
- fetch_ppc_registers (regcache, tid);
- else
- fetch_register (regcache, tid, regno);
- }
- static void
- store_vsx_registers (const struct regcache *regcache, int tid, int regno)
- {
- int ret;
- gdb_vsxregset_t regs;
- const struct regset *vsxregset = ppc_linux_vsxregset ();
- ret = ptrace (PTRACE_GETVSXREGS, tid, 0, ®s);
- if (ret < 0)
- {
- if (errno == EIO)
- {
- have_ptrace_getsetvsxregs = 0;
- return;
- }
- perror_with_name (_("Unable to fetch VSX registers"));
- }
- vsxregset->collect_regset (vsxregset, regcache, regno, ®s,
- PPC_LINUX_SIZEOF_VSXREGSET);
- ret = ptrace (PTRACE_SETVSXREGS, tid, 0, ®s);
- if (ret < 0)
- perror_with_name (_("Unable to store VSX registers"));
- }
- static void
- store_altivec_registers (const struct regcache *regcache, int tid,
- int regno)
- {
- int ret;
- gdb_vrregset_t regs;
- struct gdbarch *gdbarch = regcache->arch ();
- const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
- ret = ptrace (PTRACE_GETVRREGS, tid, 0, ®s);
- if (ret < 0)
- {
- if (errno == EIO)
- {
- have_ptrace_getvrregs = 0;
- return;
- }
- perror_with_name (_("Unable to fetch AltiVec registers"));
- }
- vrregset->collect_regset (vrregset, regcache, regno, ®s,
- PPC_LINUX_SIZEOF_VRREGSET);
- ret = ptrace (PTRACE_SETVRREGS, tid, 0, ®s);
- if (ret < 0)
- perror_with_name (_("Unable to store AltiVec registers"));
- }
- /* Assuming TID refers to an SPE process, set the top halves of TID's
- general-purpose registers and its SPE-specific registers to the
- values in EVRREGSET. If we don't support PTRACE_SETEVRREGS, do
- nothing.
- All the logic to deal with whether or not the PTRACE_GETEVRREGS and
- PTRACE_SETEVRREGS requests are supported is isolated here, and in
- get_spe_registers. */
- static void
- set_spe_registers (int tid, struct gdb_evrregset_t *evrregset)
- {
- if (have_ptrace_getsetevrregs)
- {
- if (ptrace (PTRACE_SETEVRREGS, tid, 0, evrregset) >= 0)
- return;
- else
- {
- /* EIO means that the PTRACE_SETEVRREGS request isn't
- supported; we fail silently, and don't try the call
- again. */
- if (errno == EIO)
- have_ptrace_getsetevrregs = 0;
- else
- /* Anything else needs to be reported. */
- perror_with_name (_("Unable to set SPE registers"));
- }
- }
- }
- /* Write GDB's value for the SPE-specific raw register REGNO to TID.
- If REGNO is -1, write the values of all the SPE-specific
- registers. */
- static void
- store_spe_register (const struct regcache *regcache, int tid, int regno)
- {
- struct gdbarch *gdbarch = regcache->arch ();
- ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- struct gdb_evrregset_t evrregs;
- gdb_assert (sizeof (evrregs.evr[0])
- == register_size (gdbarch, tdep->ppc_ev0_upper_regnum));
- gdb_assert (sizeof (evrregs.acc)
- == register_size (gdbarch, tdep->ppc_acc_regnum));
- gdb_assert (sizeof (evrregs.spefscr)
- == register_size (gdbarch, tdep->ppc_spefscr_regnum));
- if (regno == -1)
- /* Since we're going to write out every register, the code below
- should store to every field of evrregs; if that doesn't happen,
- make it obvious by initializing it with suspicious values. */
- memset (&evrregs, 42, sizeof (evrregs));
- else
- /* We can only read and write the entire EVR register set at a
- time, so to write just a single register, we do a
- read-modify-write maneuver. */
- get_spe_registers (tid, &evrregs);
- if (regno == -1)
- {
- int i;
- for (i = 0; i < ppc_num_gprs; i++)
- regcache->raw_collect (tdep->ppc_ev0_upper_regnum + i,
- &evrregs.evr[i]);
- }
- else if (tdep->ppc_ev0_upper_regnum <= regno
- && regno < tdep->ppc_ev0_upper_regnum + ppc_num_gprs)
- regcache->raw_collect (regno,
- &evrregs.evr[regno - tdep->ppc_ev0_upper_regnum]);
- if (regno == -1
- || regno == tdep->ppc_acc_regnum)
- regcache->raw_collect (tdep->ppc_acc_regnum,
- &evrregs.acc);
- if (regno == -1
- || regno == tdep->ppc_spefscr_regnum)
- regcache->raw_collect (tdep->ppc_spefscr_regnum,
- &evrregs.spefscr);
- /* Write back the modified register set. */
- set_spe_registers (tid, &evrregs);
- }
- static void
- store_register (const struct regcache *regcache, int tid, int regno)
- {
- struct gdbarch *gdbarch = regcache->arch ();
- ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- /* This isn't really an address. But ptrace thinks of it as one. */
- CORE_ADDR regaddr = ppc_register_u_addr (gdbarch, regno);
- int i;
- size_t bytes_to_transfer;
- gdb_byte buf[PPC_MAX_REGISTER_SIZE];
- if (altivec_register_p (gdbarch, regno))
- {
- store_altivec_registers (regcache, tid, regno);
- return;
- }
- else if (vsx_register_p (gdbarch, regno))
- {
- store_vsx_registers (regcache, tid, regno);
- return;
- }
- else if (spe_register_p (gdbarch, regno))
- {
- store_spe_register (regcache, tid, regno);
- return;
- }
- else if (regno == PPC_DSCR_REGNUM)
- {
- gdb_assert (tdep->ppc_dscr_regnum != -1);
- store_regset (regcache, tid, regno, NT_PPC_DSCR,
- PPC_LINUX_SIZEOF_DSCRREGSET,
- &ppc32_linux_dscrregset);
- return;
- }
- else if (regno == PPC_PPR_REGNUM)
- {
- gdb_assert (tdep->ppc_ppr_regnum != -1);
- store_regset (regcache, tid, regno, NT_PPC_PPR,
- PPC_LINUX_SIZEOF_PPRREGSET,
- &ppc32_linux_pprregset);
- return;
- }
- else if (regno == PPC_TAR_REGNUM)
- {
- gdb_assert (tdep->ppc_tar_regnum != -1);
- store_regset (regcache, tid, regno, NT_PPC_TAR,
- PPC_LINUX_SIZEOF_TARREGSET,
- &ppc32_linux_tarregset);
- return;
- }
- else if (PPC_IS_EBB_REGNUM (regno))
- {
- gdb_assert (tdep->have_ebb);
- store_regset (regcache, tid, regno, NT_PPC_EBB,
- PPC_LINUX_SIZEOF_EBBREGSET,
- &ppc32_linux_ebbregset);
- return;
- }
- else if (PPC_IS_PMU_REGNUM (regno))
- {
- gdb_assert (tdep->ppc_mmcr0_regnum != -1);
- store_regset (regcache, tid, regno, NT_PPC_PMU,
- PPC_LINUX_SIZEOF_PMUREGSET,
- &ppc32_linux_pmuregset);
- return;
- }
- else if (PPC_IS_TMSPR_REGNUM (regno))
- {
- gdb_assert (tdep->have_htm_spr);
- store_regset (regcache, tid, regno, NT_PPC_TM_SPR,
- PPC_LINUX_SIZEOF_TM_SPRREGSET,
- &ppc32_linux_tm_sprregset);
- return;
- }
- else if (PPC_IS_CKPTGP_REGNUM (regno))
- {
- gdb_assert (tdep->have_htm_core);
- const struct regset *cgprregset = ppc_linux_cgprregset (gdbarch);
- store_regset (regcache, tid, regno, NT_PPC_TM_CGPR,
- (tdep->wordsize == 4?
- PPC32_LINUX_SIZEOF_CGPRREGSET
- : PPC64_LINUX_SIZEOF_CGPRREGSET),
- cgprregset);
- return;
- }
- else if (PPC_IS_CKPTFP_REGNUM (regno))
- {
- gdb_assert (tdep->have_htm_fpu);
- store_regset (regcache, tid, regno, NT_PPC_TM_CFPR,
- PPC_LINUX_SIZEOF_CFPRREGSET,
- &ppc32_linux_cfprregset);
- return;
- }
- else if (PPC_IS_CKPTVMX_REGNUM (regno))
- {
- gdb_assert (tdep->have_htm_altivec);
- const struct regset *cvmxregset = ppc_linux_cvmxregset (gdbarch);
- store_regset (regcache, tid, regno, NT_PPC_TM_CVMX,
- PPC_LINUX_SIZEOF_CVMXREGSET,
- cvmxregset);
- return;
- }
- else if (PPC_IS_CKPTVSX_REGNUM (regno))
- {
- gdb_assert (tdep->have_htm_vsx);
- store_regset (regcache, tid, regno, NT_PPC_TM_CVSX,
- PPC_LINUX_SIZEOF_CVSXREGSET,
- &ppc32_linux_cvsxregset);
- return;
- }
- else if (regno == PPC_CPPR_REGNUM)
- {
- gdb_assert (tdep->ppc_cppr_regnum != -1);
- store_regset (regcache, tid, regno, NT_PPC_TM_CPPR,
- PPC_LINUX_SIZEOF_CPPRREGSET,
- &ppc32_linux_cpprregset);
- return;
- }
- else if (regno == PPC_CDSCR_REGNUM)
- {
- gdb_assert (tdep->ppc_cdscr_regnum != -1);
- store_regset (regcache, tid, regno, NT_PPC_TM_CDSCR,
- PPC_LINUX_SIZEOF_CDSCRREGSET,
- &ppc32_linux_cdscrregset);
- return;
- }
- else if (regno == PPC_CTAR_REGNUM)
- {
- gdb_assert (tdep->ppc_ctar_regnum != -1);
- store_regset (regcache, tid, regno, NT_PPC_TM_CTAR,
- PPC_LINUX_SIZEOF_CTARREGSET,
- &ppc32_linux_ctarregset);
- return;
- }
- if (regaddr == -1)
- return;
- /* First collect the register. Keep in mind that the regcache's
- idea of the register's size may not be a multiple of sizeof
- (long). */
- memset (buf, 0, sizeof buf);
- bytes_to_transfer = align_up (register_size (gdbarch, regno), sizeof (long));
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
- {
- /* Little-endian values always sit at the left end of the buffer. */
- regcache->raw_collect (regno, buf);
- }
- else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- {
- /* Big-endian values sit at the right end of the buffer. */
- size_t padding = (bytes_to_transfer - register_size (gdbarch, regno));
- regcache->raw_collect (regno, buf + padding);
- }
- for (i = 0; i < bytes_to_transfer; i += sizeof (long))
- {
- long l;
- memcpy (&l, &buf[i], sizeof (l));
- errno = 0;
- ptrace (PTRACE_POKEUSER, tid, (PTRACE_TYPE_ARG3) regaddr, l);
- regaddr += sizeof (long);
- if (errno == EIO
- && (regno == tdep->ppc_fpscr_regnum
- || regno == PPC_ORIG_R3_REGNUM
- || regno == PPC_TRAP_REGNUM))
- {
- /* Some older kernel versions don't allow fpscr, orig_r3
- or trap to be written. */
- continue;
- }
- if (errno != 0)
- {
- char message[128];
- xsnprintf (message, sizeof (message), "writing register %s (#%d)",
- gdbarch_register_name (gdbarch, regno), regno);
- perror_with_name (message);
- }
- }
- }
- /* This function actually issues the request to ptrace, telling
- it to store all general-purpose registers present in the specified
- regset.
-
- If the ptrace request does not exist, this function returns 0
- and properly sets the have_ptrace_* flag. If the request fails,
- this function calls perror_with_name. Otherwise, if the request
- succeeds, then the regcache is stored and 1 is returned. */
- static int
- store_all_gp_regs (const struct regcache *regcache, int tid, int regno)
- {
- gdb_gregset_t gregset;
- if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0)
- {
- if (errno == EIO)
- {
- have_ptrace_getsetregs = 0;
- return 0;
- }
- perror_with_name (_("Couldn't get general-purpose registers."));
- }
- fill_gregset (regcache, &gregset, regno);
- if (ptrace (PTRACE_SETREGS, tid, 0, (void *) &gregset) < 0)
- {
- if (errno == EIO)
- {
- have_ptrace_getsetregs = 0;
- return 0;
- }
- perror_with_name (_("Couldn't set general-purpose registers."));
- }
- return 1;
- }
- /* This is a wrapper for the store_all_gp_regs function. It is
- responsible for verifying if this target has the ptrace request
- that can be used to store all general-purpose registers at one
- shot. If it doesn't, then we should store them using the
- old-fashioned way, which is to iterate over the registers and
- store them one by one. */
- static void
- store_gp_regs (const struct regcache *regcache, int tid, int regno)
- {
- struct gdbarch *gdbarch = regcache->arch ();
- ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- int i;
- if (have_ptrace_getsetregs)
- if (store_all_gp_regs (regcache, tid, regno))
- return;
- /* If we hit this point, it doesn't really matter which
- architecture we are using. We just need to store the
- registers in the "old-fashioned way". */
- for (i = 0; i < ppc_num_gprs; i++)
- store_register (regcache, tid, tdep->ppc_gp0_regnum + i);
- }
- /* This function actually issues the request to ptrace, telling
- it to store all floating-point registers present in the specified
- regset.
-
- If the ptrace request does not exist, this function returns 0
- and properly sets the have_ptrace_* flag. If the request fails,
- this function calls perror_with_name. Otherwise, if the request
- succeeds, then the regcache is stored and 1 is returned. */
- static int
- store_all_fp_regs (const struct regcache *regcache, int tid, int regno)
- {
- gdb_fpregset_t fpregs;
- if (ptrace (PTRACE_GETFPREGS, tid, 0, (void *) &fpregs) < 0)
- {
- if (errno == EIO)
- {
- have_ptrace_getsetfpregs = 0;
- return 0;
- }
- perror_with_name (_("Couldn't get floating-point registers."));
- }
- fill_fpregset (regcache, &fpregs, regno);
- if (ptrace (PTRACE_SETFPREGS, tid, 0, (void *) &fpregs) < 0)
- {
- if (errno == EIO)
- {
- have_ptrace_getsetfpregs = 0;
- return 0;
- }
- perror_with_name (_("Couldn't set floating-point registers."));
- }
- return 1;
- }
- /* This is a wrapper for the store_all_fp_regs function. It is
- responsible for verifying if this target has the ptrace request
- that can be used to store all floating-point registers at one
- shot. If it doesn't, then we should store them using the
- old-fashioned way, which is to iterate over the registers and
- store them one by one. */
- static void
- store_fp_regs (const struct regcache *regcache, int tid, int regno)
- {
- struct gdbarch *gdbarch = regcache->arch ();
- ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- int i;
- if (have_ptrace_getsetfpregs)
- if (store_all_fp_regs (regcache, tid, regno))
- return;
- /* If we hit this point, it doesn't really matter which
- architecture we are using. We just need to store the
- registers in the "old-fashioned way". */
- for (i = 0; i < ppc_num_fprs; i++)
- store_register (regcache, tid, tdep->ppc_fp0_regnum + i);
- }
- static void
- store_ppc_registers (const struct regcache *regcache, int tid)
- {
- struct gdbarch *gdbarch = regcache->arch ();
- ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
-
- store_gp_regs (regcache, tid, -1);
- if (tdep->ppc_fp0_regnum >= 0)
- store_fp_regs (regcache, tid, -1);
- store_register (regcache, tid, gdbarch_pc_regnum (gdbarch));
- if (tdep->ppc_ps_regnum != -1)
- store_register (regcache, tid, tdep->ppc_ps_regnum);
- if (tdep->ppc_cr_regnum != -1)
- store_register (regcache, tid, tdep->ppc_cr_regnum);
- if (tdep->ppc_lr_regnum != -1)
- store_register (regcache, tid, tdep->ppc_lr_regnum);
- if (tdep->ppc_ctr_regnum != -1)
- store_register (regcache, tid, tdep->ppc_ctr_regnum);
- if (tdep->ppc_xer_regnum != -1)
- store_register (regcache, tid, tdep->ppc_xer_regnum);
- if (tdep->ppc_mq_regnum != -1)
- store_register (regcache, tid, tdep->ppc_mq_regnum);
- if (tdep->ppc_fpscr_regnum != -1)
- store_register (regcache, tid, tdep->ppc_fpscr_regnum);
- if (ppc_linux_trap_reg_p (gdbarch))
- {
- store_register (regcache, tid, PPC_ORIG_R3_REGNUM);
- store_register (regcache, tid, PPC_TRAP_REGNUM);
- }
- if (have_ptrace_getvrregs)
- if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1)
- store_altivec_registers (regcache, tid, -1);
- if (have_ptrace_getsetvsxregs)
- if (tdep->ppc_vsr0_upper_regnum != -1)
- store_vsx_registers (regcache, tid, -1);
- if (tdep->ppc_ev0_upper_regnum >= 0)
- store_spe_register (regcache, tid, -1);
- if (tdep->ppc_ppr_regnum != -1)
- store_regset (regcache, tid, -1, NT_PPC_PPR,
- PPC_LINUX_SIZEOF_PPRREGSET,
- &ppc32_linux_pprregset);
- if (tdep->ppc_dscr_regnum != -1)
- store_regset (regcache, tid, -1, NT_PPC_DSCR,
- PPC_LINUX_SIZEOF_DSCRREGSET,
- &ppc32_linux_dscrregset);
- if (tdep->ppc_tar_regnum != -1)
- store_regset (regcache, tid, -1, NT_PPC_TAR,
- PPC_LINUX_SIZEOF_TARREGSET,
- &ppc32_linux_tarregset);
- if (tdep->ppc_mmcr0_regnum != -1)
- store_regset (regcache, tid, -1, NT_PPC_PMU,
- PPC_LINUX_SIZEOF_PMUREGSET,
- &ppc32_linux_pmuregset);
- if (tdep->have_htm_spr)
- store_regset (regcache, tid, -1, NT_PPC_TM_SPR,
- PPC_LINUX_SIZEOF_TM_SPRREGSET,
- &ppc32_linux_tm_sprregset);
- /* Because the EBB and checkpointed HTM registers can be
- unavailable, attempts to store them here would cause this
- function to fail most of the time, so we ignore them. */
- }
- void
- ppc_linux_nat_target::store_registers (struct regcache *regcache, int regno)
- {
- pid_t tid = get_ptrace_pid (regcache->ptid ());
- if (regno >= 0)
- store_register (regcache, tid, regno);
- else
- store_ppc_registers (regcache, tid);
- }
- /* Functions for transferring registers between a gregset_t or fpregset_t
- (see sys/ucontext.h) and gdb's regcache. The word size is that used
- by the ptrace interface, not the current program's ABI. Eg. if a
- powerpc64-linux gdb is being used to debug a powerpc32-linux app, we
- read or write 64-bit gregsets. This is to suit the host libthread_db. */
- void
- supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
- {
- const struct regset *regset = ppc_linux_gregset (sizeof (long));
- ppc_supply_gregset (regset, regcache, -1, gregsetp, sizeof (*gregsetp));
- }
- void
- fill_gregset (const struct regcache *regcache,
- gdb_gregset_t *gregsetp, int regno)
- {
- const struct regset *regset = ppc_linux_gregset (sizeof (long));
- if (regno == -1)
- memset (gregsetp, 0, sizeof (*gregsetp));
- ppc_collect_gregset (regset, regcache, regno, gregsetp, sizeof (*gregsetp));
- }
- void
- supply_fpregset (struct regcache *regcache, const gdb_fpregset_t * fpregsetp)
- {
- const struct regset *regset = ppc_linux_fpregset ();
- ppc_supply_fpregset (regset, regcache, -1,
- fpregsetp, sizeof (*fpregsetp));
- }
- void
- fill_fpregset (const struct regcache *regcache,
- gdb_fpregset_t *fpregsetp, int regno)
- {
- const struct regset *regset = ppc_linux_fpregset ();
- ppc_collect_fpregset (regset, regcache, regno,
- fpregsetp, sizeof (*fpregsetp));
- }
- int
- ppc_linux_nat_target::auxv_parse (gdb_byte **readptr,
- gdb_byte *endptr, CORE_ADDR *typep,
- CORE_ADDR *valp)
- {
- int tid = inferior_ptid.lwp ();
- if (tid == 0)
- tid = inferior_ptid.pid ();
- int sizeof_auxv_field = ppc_linux_target_wordsize (tid);
- enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
- gdb_byte *ptr = *readptr;
- if (endptr == ptr)
- return 0;
- if (endptr - ptr < sizeof_auxv_field * 2)
- return -1;
- *typep = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
- ptr += sizeof_auxv_field;
- *valp = extract_unsigned_integer (ptr, sizeof_auxv_field, byte_order);
- ptr += sizeof_auxv_field;
- *readptr = ptr;
- return 1;
- }
- const struct target_desc *
- ppc_linux_nat_target::read_description ()
- {
- int tid = inferior_ptid.pid ();
- if (have_ptrace_getsetevrregs)
- {
- struct gdb_evrregset_t evrregset;
- if (ptrace (PTRACE_GETEVRREGS, tid, 0, &evrregset) >= 0)
- return tdesc_powerpc_e500l;
- /* EIO means that the PTRACE_GETEVRREGS request isn't supported.
- Anything else needs to be reported. */
- else if (errno != EIO)
- perror_with_name (_("Unable to fetch SPE registers"));
- }
- struct ppc_linux_features features = ppc_linux_no_features;
- features.wordsize = ppc_linux_target_wordsize (tid);
- CORE_ADDR hwcap = linux_get_hwcap (current_inferior ()->top_target ());
- CORE_ADDR hwcap2 = linux_get_hwcap2 (current_inferior ()->top_target ());
- if (have_ptrace_getsetvsxregs
- && (hwcap & PPC_FEATURE_HAS_VSX))
- {
- gdb_vsxregset_t vsxregset;
- if (ptrace (PTRACE_GETVSXREGS, tid, 0, &vsxregset) >= 0)
- features.vsx = true;
- /* EIO means that the PTRACE_GETVSXREGS request isn't supported.
- Anything else needs to be reported. */
- else if (errno != EIO)
- perror_with_name (_("Unable to fetch VSX registers"));
- }
- if (have_ptrace_getvrregs
- && (hwcap & PPC_FEATURE_HAS_ALTIVEC))
- {
- gdb_vrregset_t vrregset;
- if (ptrace (PTRACE_GETVRREGS, tid, 0, &vrregset) >= 0)
- features.altivec = true;
- /* EIO means that the PTRACE_GETVRREGS request isn't supported.
- Anything else needs to be reported. */
- else if (errno != EIO)
- perror_with_name (_("Unable to fetch AltiVec registers"));
- }
- features.isa205 = ppc_linux_has_isa205 (hwcap);
- if ((hwcap2 & PPC_FEATURE2_DSCR)
- && check_regset (tid, NT_PPC_PPR, PPC_LINUX_SIZEOF_PPRREGSET)
- && check_regset (tid, NT_PPC_DSCR, PPC_LINUX_SIZEOF_DSCRREGSET))
- {
- features.ppr_dscr = true;
- if ((hwcap2 & PPC_FEATURE2_ARCH_2_07)
- && (hwcap2 & PPC_FEATURE2_TAR)
- && (hwcap2 & PPC_FEATURE2_EBB)
- && check_regset (tid, NT_PPC_TAR, PPC_LINUX_SIZEOF_TARREGSET)
- && check_regset (tid, NT_PPC_EBB, PPC_LINUX_SIZEOF_EBBREGSET)
- && check_regset (tid, NT_PPC_PMU, PPC_LINUX_SIZEOF_PMUREGSET))
- {
- features.isa207 = true;
- if ((hwcap2 & PPC_FEATURE2_HTM)
- && check_regset (tid, NT_PPC_TM_SPR,
- PPC_LINUX_SIZEOF_TM_SPRREGSET))
- features.htm = true;
- }
- }
- return ppc_linux_match_description (features);
- }
- /* Routines for installing hardware watchpoints and breakpoints. When
- GDB requests a hardware watchpoint or breakpoint to be installed, we
- register the request for the pid of inferior_ptid in a map with one
- entry per process. We then issue a stop request to all the threads of
- this process, and mark a per-thread flag indicating that their debug
- registers should be updated. Right before they are next resumed, we
- remove all previously installed debug registers and install all the
- ones GDB requested. We then update a map with one entry per thread
- that keeps track of what debug registers were last installed in each
- thread.
- We use this second map to remove installed registers before installing
- the ones requested by GDB, and to copy the debug register state after
- a thread clones or forks, since depending on the kernel configuration,
- debug registers can be inherited. */
- /* Check if we support and have enough resources to install a hardware
- watchpoint or breakpoint. See the description in target.h. */
- int
- ppc_linux_nat_target::can_use_hw_breakpoint (enum bptype type, int cnt,
- int ot)
- {
- int total_hw_wp, total_hw_bp;
- m_dreg_interface.detect (inferior_ptid);
- if (m_dreg_interface.unavailable_p ())
- return 0;
- if (m_dreg_interface.hwdebug_p ())
- {
- /* When PowerPC HWDEBUG ptrace interface is available, the number of
- available hardware watchpoints and breakpoints is stored at the
- hwdebug_info struct. */
- total_hw_bp = m_dreg_interface.hwdebug_info ().num_instruction_bps;
- total_hw_wp = m_dreg_interface.hwdebug_info ().num_data_bps;
- }
- else
- {
- gdb_assert (m_dreg_interface.debugreg_p ());
- /* With the DEBUGREG ptrace interface, we should consider having 1
- hardware watchpoint and no hardware breakpoints. */
- total_hw_bp = 0;
- total_hw_wp = 1;
- }
- if (type == bp_hardware_watchpoint || type == bp_read_watchpoint
- || type == bp_access_watchpoint || type == bp_watchpoint)
- {
- if (total_hw_wp == 0)
- return 0;
- else if (cnt + ot > total_hw_wp)
- return -1;
- else
- return 1;
- }
- else if (type == bp_hardware_breakpoint)
- {
- if (total_hw_bp == 0)
- return 0;
- else if (cnt > total_hw_bp)
- return -1;
- else
- return 1;
- }
- return 0;
- }
- /* Returns 1 if we can watch LEN bytes at address ADDR, 0 otherwise. */
- int
- ppc_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
- {
- /* Handle sub-8-byte quantities. */
- if (len <= 0)
- return 0;
- m_dreg_interface.detect (inferior_ptid);
- if (m_dreg_interface.unavailable_p ())
- return 0;
- /* The PowerPC HWDEBUG ptrace interface tells if there are alignment
- restrictions for watchpoints in the processors. In that case, we use that
- information to determine the hardcoded watchable region for
- watchpoints. */
- if (m_dreg_interface.hwdebug_p ())
- {
- const struct ppc_debug_info &hwdebug_info = (m_dreg_interface
- .hwdebug_info ());
- int region_size = hwdebug_info.data_bp_alignment;
- int region_align = region_size;
- /* Embedded DAC-based processors, like the PowerPC 440 have ranged
- watchpoints and can watch any access within an arbitrary memory
- region. This is useful to watch arrays and structs, for instance. It
- takes two hardware watchpoints though. */
- if (len > 1
- && hwdebug_info.features & PPC_DEBUG_FEATURE_DATA_BP_RANGE
- && (linux_get_hwcap (current_inferior ()->top_target ())
- & PPC_FEATURE_BOOKE))
- return 2;
- /* Check if the processor provides DAWR interface. */
- if (hwdebug_info.features & PPC_DEBUG_FEATURE_DATA_BP_DAWR)
- {
- /* DAWR interface allows to watch up to 512 byte wide ranges. */
- region_size = 512;
- /* DAWR interface allows to watch up to 512 byte wide ranges which
- can't cross a 512 byte bondary on machines that doesn't have a
- second DAWR (P9 or less). */
- if (!(hwdebug_info.features & PPC_DEBUG_FEATURE_DATA_BP_ARCH_31))
- region_align = 512;
- }
- /* Server processors provide one hardware watchpoint and addr+len should
- fall in the watchable region provided by the ptrace interface. */
- if (region_align
- && (addr + len > (addr & ~(region_align - 1)) + region_size))
- return 0;
- }
- /* addr+len must fall in the 8 byte watchable region for DABR-based
- processors (i.e., server processors). Without the new PowerPC HWDEBUG
- ptrace interface, DAC-based processors (i.e., embedded processors) will
- use addresses aligned to 4-bytes due to the way the read/write flags are
- passed in the old ptrace interface. */
- else
- {
- gdb_assert (m_dreg_interface.debugreg_p ());
- if (((linux_get_hwcap (current_inferior ()->top_target ())
- & PPC_FEATURE_BOOKE)
- && (addr + len) > (addr & ~3) + 4)
- || (addr + len) > (addr & ~7) + 8)
- return 0;
- }
- return 1;
- }
- /* This function compares two ppc_hw_breakpoint structs
- field-by-field. */
- bool
- ppc_linux_nat_target::hwdebug_point_cmp (const struct ppc_hw_breakpoint &a,
- const struct ppc_hw_breakpoint &b)
- {
- return (a.trigger_type == b.trigger_type
- && a.addr_mode == b.addr_mode
- && a.condition_mode == b.condition_mode
- && a.addr == b.addr
- && a.addr2 == b.addr2
- && a.condition_value == b.condition_value);
- }
- /* Return the number of registers needed for a ranged breakpoint. */
- int
- ppc_linux_nat_target::ranged_break_num_registers ()
- {
- m_dreg_interface.detect (inferior_ptid);
- return ((m_dreg_interface.hwdebug_p ()
- && (m_dreg_interface.hwdebug_info ().features
- & PPC_DEBUG_FEATURE_INSN_BP_RANGE))?
- 2 : -1);
- }
- /* Register the hardware breakpoint described by BP_TGT, to be inserted
- when the threads of inferior_ptid are resumed. Returns 0 for success,
- or -1 if the HWDEBUG interface that we need for hardware breakpoints
- is not available. */
- int
- ppc_linux_nat_target::insert_hw_breakpoint (struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt)
- {
- struct ppc_hw_breakpoint p;
- m_dreg_interface.detect (inferior_ptid);
- if (!m_dreg_interface.hwdebug_p ())
- return -1;
- p.version = PPC_DEBUG_CURRENT_VERSION;
- p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
- p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
- p.addr = (uint64_t) (bp_tgt->placed_address = bp_tgt->reqstd_address);
- p.condition_value = 0;
- if (bp_tgt->length)
- {
- p.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
- /* The breakpoint will trigger if the address of the instruction is
- within the defined range, as follows: p.addr <= address < p.addr2. */
- p.addr2 = (uint64_t) bp_tgt->placed_address + bp_tgt->length;
- }
- else
- {
- p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
- p.addr2 = 0;
- }
- register_hw_breakpoint (inferior_ptid.pid (), p);
- return 0;
- }
- /* Clear a registration for the hardware breakpoint given by type BP_TGT.
- It will be removed from the threads of inferior_ptid when they are
- next resumed. Returns 0 for success, or -1 if the HWDEBUG interface
- that we need for hardware breakpoints is not available. */
- int
- ppc_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
- struct bp_target_info *bp_tgt)
- {
- struct ppc_hw_breakpoint p;
- m_dreg_interface.detect (inferior_ptid);
- if (!m_dreg_interface.hwdebug_p ())
- return -1;
- p.version = PPC_DEBUG_CURRENT_VERSION;
- p.trigger_type = PPC_BREAKPOINT_TRIGGER_EXECUTE;
- p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
- p.addr = (uint64_t) bp_tgt->placed_address;
- p.condition_value = 0;
- if (bp_tgt->length)
- {
- p.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
- /* The breakpoint will trigger if the address of the instruction is within
- the defined range, as follows: p.addr <= address < p.addr2. */
- p.addr2 = (uint64_t) bp_tgt->placed_address + bp_tgt->length;
- }
- else
- {
- p.addr_mode = PPC_BREAKPOINT_MODE_EXACT;
- p.addr2 = 0;
- }
- clear_hw_breakpoint (inferior_ptid.pid (), p);
- return 0;
- }
- /* Return the trigger value to set in a ppc_hw_breakpoint object for a
- given hardware watchpoint TYPE. We assume type is not hw_execute. */
- int
- ppc_linux_nat_target::get_trigger_type (enum target_hw_bp_type type)
- {
- int t;
- if (type == hw_read)
- t = PPC_BREAKPOINT_TRIGGER_READ;
- else if (type == hw_write)
- t = PPC_BREAKPOINT_TRIGGER_WRITE;
- else
- t = PPC_BREAKPOINT_TRIGGER_READ | PPC_BREAKPOINT_TRIGGER_WRITE;
- return t;
- }
- /* Register a new masked watchpoint at ADDR using the mask MASK, to be
- inserted when the threads of inferior_ptid are resumed. RW may be
- hw_read for a read watchpoint, hw_write for a write watchpoint or
- hw_access for an access watchpoint. */
- int
- ppc_linux_nat_target::insert_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
- target_hw_bp_type rw)
- {
- struct ppc_hw_breakpoint p;
- gdb_assert (m_dreg_interface.hwdebug_p ());
- p.version = PPC_DEBUG_CURRENT_VERSION;
- p.trigger_type = get_trigger_type (rw);
- p.addr_mode = PPC_BREAKPOINT_MODE_MASK;
- p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
- p.addr = addr;
- p.addr2 = mask;
- p.condition_value = 0;
- register_hw_breakpoint (inferior_ptid.pid (), p);
- return 0;
- }
- /* Clear a registration for a masked watchpoint at ADDR with the mask
- MASK. It will be removed from the threads of inferior_ptid when they
- are next resumed. RW may be hw_read for a read watchpoint, hw_write
- for a write watchpoint or hw_access for an access watchpoint. */
- int
- ppc_linux_nat_target::remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
- target_hw_bp_type rw)
- {
- struct ppc_hw_breakpoint p;
- gdb_assert (m_dreg_interface.hwdebug_p ());
- p.version = PPC_DEBUG_CURRENT_VERSION;
- p.trigger_type = get_trigger_type (rw);
- p.addr_mode = PPC_BREAKPOINT_MODE_MASK;
- p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
- p.addr = addr;
- p.addr2 = mask;
- p.condition_value = 0;
- clear_hw_breakpoint (inferior_ptid.pid (), p);
- return 0;
- }
- /* Check whether we have at least one free DVC register for the threads
- of the pid of inferior_ptid. */
- bool
- ppc_linux_nat_target::can_use_watchpoint_cond_accel (void)
- {
- m_dreg_interface.detect (inferior_ptid);
- if (!m_dreg_interface.hwdebug_p ())
- return false;
- int cnt = m_dreg_interface.hwdebug_info ().num_condition_regs;
- if (cnt == 0)
- return false;
- auto process_it = m_process_info.find (inferior_ptid.pid ());
- /* No breakpoints or watchpoints have been requested for this process,
- we have at least one free DVC register. */
- if (process_it == m_process_info.end ())
- return true;
- for (const ppc_hw_breakpoint &bp : process_it->second.requested_hw_bps)
- if (bp.condition_mode != PPC_BREAKPOINT_CONDITION_NONE)
- cnt--;
- if (cnt <= 0)
- return false;
- return true;
- }
- /* Calculate the enable bits and the contents of the Data Value Compare
- debug register present in BookE processors.
- ADDR is the address to be watched, LEN is the length of watched data
- and DATA_VALUE is the value which will trigger the watchpoint.
- On exit, CONDITION_MODE will hold the enable bits for the DVC, and
- CONDITION_VALUE will hold the value which should be put in the
- DVC register. */
- void
- ppc_linux_nat_target::calculate_dvc (CORE_ADDR addr, int len,
- CORE_ADDR data_value,
- uint32_t *condition_mode,
- uint64_t *condition_value)
- {
- const struct ppc_debug_info &hwdebug_info = (m_dreg_interface.
- hwdebug_info ());
- int i, num_byte_enable, align_offset, num_bytes_off_dvc,
- rightmost_enabled_byte;
- CORE_ADDR addr_end_data, addr_end_dvc;
- /* The DVC register compares bytes within fixed-length windows which
- are word-aligned, with length equal to that of the DVC register.
- We need to calculate where our watch region is relative to that
- window and enable comparison of the bytes which fall within it. */
- align_offset = addr % hwdebug_info.sizeof_condition;
- addr_end_data = addr + len;
- addr_end_dvc = (addr - align_offset
- + hwdebug_info.sizeof_condition);
- num_bytes_off_dvc = (addr_end_data > addr_end_dvc)?
- addr_end_data - addr_end_dvc : 0;
- num_byte_enable = len - num_bytes_off_dvc;
- /* Here, bytes are numbered from right to left. */
- rightmost_enabled_byte = (addr_end_data < addr_end_dvc)?
- addr_end_dvc - addr_end_data : 0;
- *condition_mode = PPC_BREAKPOINT_CONDITION_AND;
- for (i = 0; i < num_byte_enable; i++)
- *condition_mode
- |= PPC_BREAKPOINT_CONDITION_BE (i + rightmost_enabled_byte);
- /* Now we need to match the position within the DVC of the comparison
- value with where the watch region is relative to the window
- (i.e., the ALIGN_OFFSET). */
- *condition_value = ((uint64_t) data_value >> num_bytes_off_dvc * 8
- << rightmost_enabled_byte * 8);
- }
- /* Return the number of memory locations that need to be accessed to
- evaluate the expression which generated the given value chain.
- Returns -1 if there's any register access involved, or if there are
- other kinds of values which are not acceptable in a condition
- expression (e.g., lval_computed or lval_internalvar). */
- int
- ppc_linux_nat_target::num_memory_accesses (const std::vector<value_ref_ptr>
- &chain)
- {
- int found_memory_cnt = 0;
- /* 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 determine the memory locations involved in the evaluation
- of an expression.
- 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 contains an inferior function call.
- FIXME. */
- for (const value_ref_ptr &iter : chain)
- {
- struct value *v = iter.get ();
- /* Constants and values from the history are fine. */
- if (VALUE_LVAL (v) == not_lval || deprecated_value_modifiable (v) == 0)
- continue;
- else if (VALUE_LVAL (v) == lval_memory)
- {
- /* A lazy memory lvalue 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'). */
- if (!value_lazy (v))
- found_memory_cnt++;
- }
- /* Other kinds of values are not fine. */
- else
- return -1;
- }
- return found_memory_cnt;
- }
- /* Verifies whether the expression COND can be implemented using the
- DVC (Data Value Compare) register in BookE processors. The expression
- must test the watch value for equality with a constant expression.
- If the function returns 1, DATA_VALUE will contain the constant against
- which the watch value should be compared and LEN will contain the size
- of the constant. */
- int
- ppc_linux_nat_target::check_condition (CORE_ADDR watch_addr,
- struct expression *cond,
- CORE_ADDR *data_value, int *len)
- {
- int num_accesses_left, num_accesses_right;
- struct value *left_val, *right_val;
- std::vector<value_ref_ptr> left_chain, right_chain;
- expr::equal_operation *eqop
- = dynamic_cast<expr::equal_operation *> (cond->op.get ());
- if (eqop == nullptr)
- return 0;
- expr::operation *lhs = eqop->get_lhs ();
- expr::operation *rhs = eqop->get_rhs ();
- fetch_subexp_value (cond, lhs, &left_val, NULL, &left_chain, false);
- num_accesses_left = num_memory_accesses (left_chain);
- if (left_val == NULL || num_accesses_left < 0)
- return 0;
- fetch_subexp_value (cond, rhs, &right_val, NULL, &right_chain, false);
- num_accesses_right = num_memory_accesses (right_chain);
- if (right_val == NULL || num_accesses_right < 0)
- return 0;
- if (num_accesses_left == 1 && num_accesses_right == 0
- && VALUE_LVAL (left_val) == lval_memory
- && value_address (left_val) == watch_addr)
- {
- *data_value = value_as_long (right_val);
- /* DATA_VALUE is the constant in RIGHT_VAL, but actually has
- the same type as the memory region referenced by LEFT_VAL. */
- *len = TYPE_LENGTH (check_typedef (value_type (left_val)));
- }
- else if (num_accesses_left == 0 && num_accesses_right == 1
- && VALUE_LVAL (right_val) == lval_memory
- && value_address (right_val) == watch_addr)
- {
- *data_value = value_as_long (left_val);
- /* DATA_VALUE is the constant in LEFT_VAL, but actually has
- the same type as the memory region referenced by RIGHT_VAL. */
- *len = TYPE_LENGTH (check_typedef (value_type (right_val)));
- }
- else
- return 0;
- return 1;
- }
- /* Return true if the target is capable of using hardware to evaluate the
- condition expression, thus only triggering the watchpoint when it is
- true. */
- bool
- ppc_linux_nat_target::can_accel_watchpoint_condition (CORE_ADDR addr,
- int len, int rw,
- struct expression *cond)
- {
- CORE_ADDR data_value;
- m_dreg_interface.detect (inferior_ptid);
- return (m_dreg_interface.hwdebug_p ()
- && (m_dreg_interface.hwdebug_info ().num_condition_regs > 0)
- && check_condition (addr, cond, &data_value, &len));
- }
- /* Set up P with the parameters necessary to request a watchpoint covering
- LEN bytes starting at ADDR and if possible with condition expression COND
- evaluated by hardware. INSERT tells if we are creating a request for
- inserting or removing the watchpoint. */
- void
- ppc_linux_nat_target::create_watchpoint_request (struct ppc_hw_breakpoint *p,
- CORE_ADDR addr, int len,
- enum target_hw_bp_type type,
- struct expression *cond,
- int insert)
- {
- const struct ppc_debug_info &hwdebug_info = (m_dreg_interface
- .hwdebug_info ());
- if (len == 1
- || !(hwdebug_info.features & PPC_DEBUG_FEATURE_DATA_BP_RANGE))
- {
- int use_condition;
- CORE_ADDR data_value;
- use_condition = (insert? can_use_watchpoint_cond_accel ()
- : hwdebug_info.num_condition_regs > 0);
- if (cond && use_condition && check_condition (addr, cond,
- &data_value, &len))
- calculate_dvc (addr, len, data_value, &p->condition_mode,
- &p->condition_value);
- else
- {
- p->condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
- p->condition_value = 0;
- }
- p->addr_mode = PPC_BREAKPOINT_MODE_EXACT;
- p->addr2 = 0;
- }
- else
- {
- p->addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE;
- p->condition_mode = PPC_BREAKPOINT_CONDITION_NONE;
- p->condition_value = 0;
- /* The watchpoint will trigger if the address of the memory access is
- within the defined range, as follows: p->addr <= address < p->addr2.
- Note that the above sentence just documents how ptrace interprets
- its arguments; the watchpoint is set to watch the range defined by
- the user _inclusively_, as specified by the user interface. */
- p->addr2 = (uint64_t) addr + len;
- }
- p->version = PPC_DEBUG_CURRENT_VERSION;
- p->trigger_type = get_trigger_type (type);
- p->addr = (uint64_t) addr;
- }
- /* Register a watchpoint, to be inserted when the threads of the group of
- inferior_ptid are next resumed. Returns 0 on success, and -1 if there
- is no ptrace interface available to install the watchpoint. */
- int
- ppc_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
- enum target_hw_bp_type type,
- struct expression *cond)
- {
- m_dreg_interface.detect (inferior_ptid);
- if (m_dreg_interface.unavailable_p ())
- return -1;
- if (m_dreg_interface.hwdebug_p ())
- {
- struct ppc_hw_breakpoint p;
- create_watchpoint_request (&p, addr, len, type, cond, 1);
- register_hw_breakpoint (inferior_ptid.pid (), p);
- }
- else
- {
- gdb_assert (m_dreg_interface.debugreg_p ());
- long wp_value;
- long read_mode, write_mode;
- if (linux_get_hwcap (current_inferior ()->top_target ())
- & PPC_FEATURE_BOOKE)
- {
- /* PowerPC 440 requires only the read/write flags to be passed
- to the kernel. */
- read_mode = 1;
- write_mode = 2;
- }
- else
- {
- /* PowerPC 970 and other DABR-based processors are required to pass
- the Breakpoint Translation bit together with the flags. */
- read_mode = 5;
- write_mode = 6;
- }
- wp_value = addr & ~(read_mode | write_mode);
- switch (type)
- {
- case hw_read:
- /* Set read and translate bits. */
- wp_value |= read_mode;
- break;
- case hw_write:
- /* Set write and translate bits. */
- wp_value |= write_mode;
- break;
- case hw_access:
- /* Set read, write and translate bits. */
- wp_value |= read_mode | write_mode;
- break;
- }
- register_wp (inferior_ptid.pid (), wp_value);
- }
- return 0;
- }
- /* Clear a registration for a hardware watchpoint. It will be removed
- from the threads of the group of inferior_ptid when they are next
- resumed. */
- int
- ppc_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len,
- enum target_hw_bp_type type,
- struct expression *cond)
- {
- gdb_assert (!m_dreg_interface.unavailable_p ());
- if (m_dreg_interface.hwdebug_p ())
- {
- struct ppc_hw_breakpoint p;
- create_watchpoint_request (&p, addr, len, type, cond, 0);
- clear_hw_breakpoint (inferior_ptid.pid (), p);
- }
- else
- {
- gdb_assert (m_dreg_interface.debugreg_p ());
- clear_wp (inferior_ptid.pid ());
- }
- return 0;
- }
- /* Clean up the per-process info associated with PID. When using the
- HWDEBUG interface, we also erase the per-thread state of installed
- debug registers for all the threads that belong to the group of PID.
- Usually the thread state is cleaned up by low_delete_thread. We also
- do it here because low_new_thread is not called for the initial LWP,
- so low_delete_thread won't be able to clean up this state. */
- void
- ppc_linux_nat_target::low_forget_process (pid_t pid)
- {
- if ((!m_dreg_interface.detected_p ())
- || (m_dreg_interface.unavailable_p ()))
- return;
- ptid_t pid_ptid (pid, 0, 0);
- m_process_info.erase (pid);
- if (m_dreg_interface.hwdebug_p ())
- {
- for (auto it = m_installed_hw_bps.begin ();
- it != m_installed_hw_bps.end ();)
- {
- if (it->first.matches (pid_ptid))
- it = m_installed_hw_bps.erase (it);
- else
- it++;
- }
- }
- }
- /* Copy the per-process state associated with the pid of PARENT to the
- sate of CHILD_PID. GDB expects that a forked process will have the
- same hardware breakpoints and watchpoints as the parent.
- If we're using the HWDEBUG interface, also copy the thread debug
- register state for the ptid of PARENT to the state for CHILD_PID.
- Like for clone events, we assume the kernel will copy the debug
- registers from the parent thread to the child. The
- low_prepare_to_resume function is made to work even if it doesn't.
- We copy the thread state here and not in low_new_thread since we don't
- have the pid of the parent in low_new_thread. Even if we did,
- low_new_thread might not be called immediately after the fork event is
- detected. For instance, with the checkpointing system (see
- linux-fork.c), the thread won't be added until GDB decides to switch
- to a new checkpointed process. At that point, the debug register
- state of the parent thread is unlikely to correspond to the state it
- had at the point when it forked. */
- void
- ppc_linux_nat_target::low_new_fork (struct lwp_info *parent,
- pid_t child_pid)
- {
- if ((!m_dreg_interface.detected_p ())
- || (m_dreg_interface.unavailable_p ()))
- return;
- auto process_it = m_process_info.find (parent->ptid.pid ());
- if (process_it != m_process_info.end ())
- m_process_info[child_pid] = m_process_info[parent->ptid.pid ()];
- if (m_dreg_interface.hwdebug_p ())
- {
- ptid_t child_ptid (child_pid, child_pid, 0);
- copy_thread_dreg_state (parent->ptid, child_ptid);
- }
- }
- /* Copy the thread debug register state from the PARENT thread to the the
- state for CHILD_LWP, if we're using the HWDEBUG interface. We assume
- the kernel copies the debug registers from one thread to another after
- a clone event. The low_prepare_to_resume function is made to work
- even if it doesn't. */
- void
- ppc_linux_nat_target::low_new_clone (struct lwp_info *parent,
- pid_t child_lwp)
- {
- if ((!m_dreg_interface.detected_p ())
- || (m_dreg_interface.unavailable_p ()))
- return;
- if (m_dreg_interface.hwdebug_p ())
- {
- ptid_t child_ptid (parent->ptid.pid (), child_lwp, 0);
- copy_thread_dreg_state (parent->ptid, child_ptid);
- }
- }
- /* Initialize the arch-specific thread state for LP so that it contains
- the ptid for lp, so that we can use it in low_delete_thread. Mark the
- new thread LP as stale so that we update its debug registers before
- resuming it. This is not called for the initial thread. */
- void
- ppc_linux_nat_target::low_new_thread (struct lwp_info *lp)
- {
- init_arch_lwp_info (lp);
- mark_thread_stale (lp);
- }
- /* Delete the per-thread debug register stale flag. */
- void
- ppc_linux_nat_target::low_delete_thread (struct arch_lwp_info
- *lp_arch_info)
- {
- if (lp_arch_info != NULL)
- {
- if (m_dreg_interface.detected_p ()
- && m_dreg_interface.hwdebug_p ())
- m_installed_hw_bps.erase (lp_arch_info->lwp_ptid);
- xfree (lp_arch_info);
- }
- }
- /* Install or delete debug registers in thread LP so that it matches what
- GDB requested before it is resumed. */
- void
- ppc_linux_nat_target::low_prepare_to_resume (struct lwp_info *lp)
- {
- if ((!m_dreg_interface.detected_p ())
- || (m_dreg_interface.unavailable_p ()))
- return;
- /* We have to re-install or clear the debug registers if we set the
- stale flag.
- In addition, some kernels configurations can disable a hardware
- watchpoint after it is hit. Usually, GDB will remove and re-install
- a hardware watchpoint when the thread stops if "breakpoint
- always-inserted" is off, or to single-step a watchpoint. But so
- that we don't rely on this behavior, if we stop due to a hardware
- breakpoint or watchpoint, we also refresh our debug registers. */
- arch_lwp_info *lp_arch_info = get_arch_lwp_info (lp);
- bool stale_dregs = (lp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT
- || lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT
- || lp_arch_info->debug_regs_stale);
- if (!stale_dregs)
- return;
- gdb_assert (lp->ptid.lwp_p ());
- auto process_it = m_process_info.find (lp->ptid.pid ());
- if (m_dreg_interface.hwdebug_p ())
- {
- /* First, delete any hardware watchpoint or breakpoint installed in
- the inferior and update the thread state. */
- auto installed_it = m_installed_hw_bps.find (lp->ptid);
- if (installed_it != m_installed_hw_bps.end ())
- {
- auto &bp_list = installed_it->second;
- for (auto bp_it = bp_list.begin (); bp_it != bp_list.end ();)
- {
- /* We ignore ENOENT to account for various possible kernel
- behaviors, e.g. the kernel might or might not copy debug
- registers across forks and clones, and we always copy
- the debug register state when fork and clone events are
- detected. */
- if (ptrace (PPC_PTRACE_DELHWDEBUG, lp->ptid.lwp (), 0,
- bp_it->first) < 0)
- if (errno != ENOENT)
- perror_with_name (_("Error deleting hardware "
- "breakpoint or watchpoint"));
- /* We erase the entries one at a time after successfuly
- removing the corresponding slot form the thread so that
- if we throw an exception above in a future iteration the
- map remains consistent. */
- bp_it = bp_list.erase (bp_it);
- }
- gdb_assert (bp_list.empty ());
- }
- /* Now we install all the requested hardware breakpoints and
- watchpoints and update the thread state. */
- if (process_it != m_process_info.end ())
- {
- auto &bp_list = m_installed_hw_bps[lp->ptid];
- for (ppc_hw_breakpoint bp
- : process_it->second.requested_hw_bps)
- {
- long slot = ptrace (PPC_PTRACE_SETHWDEBUG, lp->ptid.lwp (),
- 0, &bp);
- if (slot < 0)
- perror_with_name (_("Error setting hardware "
- "breakpoint or watchpoint"));
- /* Keep track of which slots we installed in this
- thread. */
- bp_list.emplace (bp_list.begin (), slot, bp);
- }
- }
- }
- else
- {
- gdb_assert (m_dreg_interface.debugreg_p ());
- /* Passing 0 to PTRACE_SET_DEBUGREG will clear the watchpoint. We
- always clear the watchpoint instead of just overwriting it, in
- case there is a request for a new watchpoint, because on some
- older kernel versions and configurations simply overwriting the
- watchpoint after it was hit would not re-enable it. */
- if (ptrace (PTRACE_SET_DEBUGREG, lp->ptid.lwp (), 0, 0) < 0)
- perror_with_name (_("Error clearing hardware watchpoint"));
- /* GDB requested a watchpoint to be installed. */
- if (process_it != m_process_info.end ()
- && process_it->second.requested_wp_val.has_value ())
- {
- long wp = *(process_it->second.requested_wp_val);
- if (ptrace (PTRACE_SET_DEBUGREG, lp->ptid.lwp (), 0, wp) < 0)
- perror_with_name (_("Error setting hardware watchpoint"));
- }
- }
- lp_arch_info->debug_regs_stale = false;
- }
- /* Return true if INFERIOR_PTID is known to have been stopped by a
- hardware watchpoint, false otherwise. If true is returned, write the
- address that the kernel reported as causing the SIGTRAP in ADDR_P. */
- bool
- ppc_linux_nat_target::low_stopped_data_address (CORE_ADDR *addr_p)
- {
- siginfo_t siginfo;
- if (!linux_nat_get_siginfo (inferior_ptid, &siginfo))
- return false;
- if (siginfo.si_signo != SIGTRAP
- || (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
- return false;
- gdb_assert (!m_dreg_interface.unavailable_p ());
- /* Check if this signal corresponds to a hardware breakpoint. We only
- need to check this if we're using the HWDEBUG interface, since the
- DEBUGREG interface only allows setting one hardware watchpoint. */
- if (m_dreg_interface.hwdebug_p ())
- {
- /* The index (or slot) of the *point is passed in the si_errno
- field. Currently, this is only the case if the kernel was
- configured with CONFIG_PPC_ADV_DEBUG_REGS. If not, we assume
- the kernel will set si_errno to a value that doesn't correspond
- to any real slot. */
- int slot = siginfo.si_errno;
- auto installed_it = m_installed_hw_bps.find (inferior_ptid);
- /* We must have installed slots for the thread if it got a
- TRAP_HWBKPT signal. */
- gdb_assert (installed_it != m_installed_hw_bps.end ());
- for (const auto & slot_bp_pair : installed_it->second)
- if (slot_bp_pair.first == slot
- && (slot_bp_pair.second.trigger_type
- == PPC_BREAKPOINT_TRIGGER_EXECUTE))
- return false;
- }
- *addr_p = (CORE_ADDR) (uintptr_t) siginfo.si_addr;
- return true;
- }
- /* Return true if INFERIOR_PTID is known to have been stopped by a
- hardware watchpoint, false otherwise. */
- bool
- ppc_linux_nat_target::low_stopped_by_watchpoint ()
- {
- CORE_ADDR addr;
- return low_stopped_data_address (&addr);
- }
- bool
- ppc_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
- CORE_ADDR start,
- int length)
- {
- gdb_assert (!m_dreg_interface.unavailable_p ());
- int mask;
- if (m_dreg_interface.hwdebug_p ()
- && (linux_get_hwcap (current_inferior ()->top_target ())
- & PPC_FEATURE_BOOKE))
- return start <= addr && start + length >= addr;
- else if (linux_get_hwcap (current_inferior ()->top_target ())
- & PPC_FEATURE_BOOKE)
- mask = 3;
- else
- mask = 7;
- addr &= ~mask;
- /* Check whether [start, start+length-1] intersects [addr, addr+mask]. */
- return start <= addr + mask && start + length - 1 >= addr;
- }
- /* Return the number of registers needed for a masked hardware watchpoint. */
- int
- ppc_linux_nat_target::masked_watch_num_registers (CORE_ADDR addr,
- CORE_ADDR mask)
- {
- m_dreg_interface.detect (inferior_ptid);
- if (!m_dreg_interface.hwdebug_p ()
- || (m_dreg_interface.hwdebug_info ().features
- & PPC_DEBUG_FEATURE_DATA_BP_MASK) == 0)
- return -1;
- else if ((mask & 0xC0000000) != 0xC0000000)
- {
- warning (_("The given mask covers kernel address space "
- "and cannot be used.\n"));
- return -2;
- }
- else
- return 2;
- }
- /* Copy the per-thread debug register state, if any, from thread
- PARENT_PTID to thread CHILD_PTID, if the debug register being used is
- HWDEBUG. */
- void
- ppc_linux_nat_target::copy_thread_dreg_state (const ptid_t &parent_ptid,
- const ptid_t &child_ptid)
- {
- gdb_assert (m_dreg_interface.hwdebug_p ());
- auto installed_it = m_installed_hw_bps.find (parent_ptid);
- if (installed_it != m_installed_hw_bps.end ())
- m_installed_hw_bps[child_ptid] = m_installed_hw_bps[parent_ptid];
- }
- /* Mark the debug register stale flag for the new thread, if we have
- already detected which debug register interface we use. */
- void
- ppc_linux_nat_target::mark_thread_stale (struct lwp_info *lp)
- {
- if ((!m_dreg_interface.detected_p ())
- || (m_dreg_interface.unavailable_p ()))
- return;
- arch_lwp_info *lp_arch_info = get_arch_lwp_info (lp);
- lp_arch_info->debug_regs_stale = true;
- }
- /* Mark all the threads of the group of PID as stale with respect to
- debug registers and issue a stop request to each such thread that
- isn't already stopped. */
- void
- ppc_linux_nat_target::mark_debug_registers_changed (pid_t pid)
- {
- /* We do this in two passes to make sure all threads are marked even if
- we get an exception when stopping one of them. */
- iterate_over_lwps (ptid_t (pid),
- [this] (struct lwp_info *lp) -> int {
- this->mark_thread_stale (lp);
- return 0;
- });
- iterate_over_lwps (ptid_t (pid),
- [] (struct lwp_info *lp) -> int {
- if (!lwp_is_stopped (lp))
- linux_stop_lwp (lp);
- return 0;
- });
- }
- /* Register a hardware breakpoint or watchpoint BP for the pid PID, then
- mark the stale flag for all threads of the group of PID, and issue a
- stop request for them. The breakpoint or watchpoint will be installed
- the next time each thread is resumed. Should only be used if the
- debug register interface is HWDEBUG. */
- void
- ppc_linux_nat_target::register_hw_breakpoint (pid_t pid,
- const struct
- ppc_hw_breakpoint &bp)
- {
- gdb_assert (m_dreg_interface.hwdebug_p ());
- m_process_info[pid].requested_hw_bps.push_back (bp);
- mark_debug_registers_changed (pid);
- }
- /* Clear a registration for a hardware breakpoint or watchpoint BP for
- the pid PID, then mark the stale flag for all threads of the group of
- PID, and issue a stop request for them. The breakpoint or watchpoint
- will be removed the next time each thread is resumed. Should only be
- used if the debug register interface is HWDEBUG. */
- void
- ppc_linux_nat_target::clear_hw_breakpoint (pid_t pid,
- const struct ppc_hw_breakpoint &bp)
- {
- gdb_assert (m_dreg_interface.hwdebug_p ());
- auto process_it = m_process_info.find (pid);
- gdb_assert (process_it != m_process_info.end ());
- auto bp_it = std::find_if (process_it->second.requested_hw_bps.begin (),
- process_it->second.requested_hw_bps.end (),
- [&bp, this]
- (const struct ppc_hw_breakpoint &curr)
- { return hwdebug_point_cmp (bp, curr); }
- );
- /* If GDB is removing a watchpoint, it must have been inserted. */
- gdb_assert (bp_it != process_it->second.requested_hw_bps.end ());
- process_it->second.requested_hw_bps.erase (bp_it);
- mark_debug_registers_changed (pid);
- }
- /* Register the hardware watchpoint value WP_VALUE for the pid PID,
- then mark the stale flag for all threads of the group of PID, and
- issue a stop request for them. The breakpoint or watchpoint will be
- installed the next time each thread is resumed. Should only be used
- if the debug register interface is DEBUGREG. */
- void
- ppc_linux_nat_target::register_wp (pid_t pid, long wp_value)
- {
- gdb_assert (m_dreg_interface.debugreg_p ());
- /* Our other functions should have told GDB that we only have one
- hardware watchpoint with this interface. */
- gdb_assert (!m_process_info[pid].requested_wp_val.has_value ());
- m_process_info[pid].requested_wp_val.emplace (wp_value);
- mark_debug_registers_changed (pid);
- }
- /* Clear the hardware watchpoint registration for the pid PID, then mark
- the stale flag for all threads of the group of PID, and issue a stop
- request for them. The breakpoint or watchpoint will be installed the
- next time each thread is resumed. Should only be used if the debug
- register interface is DEBUGREG. */
- void
- ppc_linux_nat_target::clear_wp (pid_t pid)
- {
- gdb_assert (m_dreg_interface.debugreg_p ());
- auto process_it = m_process_info.find (pid);
- gdb_assert (process_it != m_process_info.end ());
- gdb_assert (process_it->second.requested_wp_val.has_value ());
- process_it->second.requested_wp_val.reset ();
- mark_debug_registers_changed (pid);
- }
- /* Initialize the arch-specific thread state for LWP, if it not already
- created. */
- void
- ppc_linux_nat_target::init_arch_lwp_info (struct lwp_info *lp)
- {
- if (lwp_arch_private_info (lp) == NULL)
- {
- lwp_set_arch_private_info (lp, XCNEW (struct arch_lwp_info));
- lwp_arch_private_info (lp)->debug_regs_stale = false;
- lwp_arch_private_info (lp)->lwp_ptid = lp->ptid;
- }
- }
- /* Get the arch-specific thread state for LWP, creating it if
- necessary. */
- arch_lwp_info *
- ppc_linux_nat_target::get_arch_lwp_info (struct lwp_info *lp)
- {
- init_arch_lwp_info (lp);
- return lwp_arch_private_info (lp);
- }
- void _initialize_ppc_linux_nat ();
- void
- _initialize_ppc_linux_nat ()
- {
- linux_target = &the_ppc_linux_nat_target;
- /* Register the target. */
- add_inf_child_target (linux_target);
- }
|