1+ #include " libpstack/arch.h"
12#include " libpstack/dwarf.h"
23#include " libpstack/elf.h"
34#include " libpstack/proc.h"
78extern std::ostream & operator << (std::ostream &os, const pstack::Dwarf::DIE &);
89
910namespace pstack ::Procman {
10- void
11- StackFrame::setCoreRegs (const Elf::CoreRegisters &sys)
12- {
13- #define REGMAP (number, field ) Elf::setReg(regs, number, sys.field);
14- #include " libpstack/archreg.h"
15- #undef REGMAP
16- }
1711
18- void
19- StackFrame::getCoreRegs (Elf::CoreRegisters &core) const
20- {
21- #define REGMAP (number, field ) core.field = Elf::getReg(regs, number);
22- #include " libpstack/archreg.h"
23- #undef REGMAP
12+ struct RegisterFromReader {
13+ const Reader &reader;
14+ off_t offset;
15+ public:
16+ explicit RegisterFromReader (const Reader &reader, off_t offset) : reader(reader), offset(offset) { }
17+ };
18+
19+ template <typename T>
20+ auto get ( const RegisterFromReader &rfr ) -> T {
21+ T t = rfr.reader .readObj <T>(rfr.offset );
22+ return t;
2423}
2524
26- Elf::Addr
25+ gpreg
2726StackFrame::rawIP () const
2827{
28+ return
2929#ifdef __aarch64__
30- // remove RA signing artefacts.
31- return 0xffffffffffff & Elf::getReg (regs, IPREG);
32- #else
33- return Elf::getReg (regs, IPREG);
30+ 0xffffffffffff &
3431#endif
32+ std::get<gpreg>(regs.getDwarf (IPREG));
3533}
3634
3735ProcessLocation
@@ -57,7 +55,7 @@ StackFrame::scopeIP(Process &proc) const
5755 // Finally, for the function that was running when the signal was invoked -
5856 // The signal was invoked asynchronously, so again, we have no call
5957 // instruction to walk back into.
60- auto raw = rawIP ();
58+ auto raw = Elf::Addr ( rawIP () );
6159 if (raw == 0 )
6260 return { proc, raw };
6361 if (mechanism == UnwindMechanism::MACHINEREGS
@@ -283,7 +281,7 @@ ExpressionStack::eval(Process &proc, Dwarf::DWARFReader &r, const StackFrame *fr
283281 case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27:
284282 case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: {
285283 auto offset = r.getsleb128 ();
286- push (Elf::getReg (frame->regs , op - DW_OP_breg0) + offset);
284+ push (std::get<gpreg> (frame->regs . getDwarf ( op - DW_OP_breg0) ) + offset);
287285 break ;
288286 }
289287
@@ -444,10 +442,10 @@ ExpressionStack::eval(Process &proc, Dwarf::DWARFReader &r, const StackFrame *fr
444442 case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31:
445443 isValue = true ;
446444 inReg = op - DW_OP_reg0;
447- push (Elf::getReg (frame->regs , op - DW_OP_reg0));
445+ push (std::get<gpreg> (frame->regs . getDwarf ( op - DW_OP_reg0) ));
448446 break ;
449447 case DW_OP_regx:
450- push (Elf::getReg (frame->regs , int ( r.getsleb128 ())));
448+ push (std::get<gpreg> (frame->regs . getDwarf ( size_t ( r.getsleb128 () ))));
451449 break ;
452450
453451 case DW_OP_entry_value:
@@ -505,14 +503,14 @@ ExpressionStack::eval(Process &proc, Dwarf::DWARFReader &r, const StackFrame *fr
505503}
506504
507505
508- StackFrame::StackFrame (UnwindMechanism mechanism, const Elf:: CoreRegisters ®s_)
506+ StackFrame::StackFrame (UnwindMechanism mechanism, const CoreRegisters ®s_)
509507 : regs(regs_)
510508 , cfa(0 )
511509 , mechanism(mechanism)
512510{
513511}
514512
515- std::optional<Elf:: CoreRegisters> StackFrame::unwind (Process &p) {
513+ std::optional<CoreRegisters> StackFrame::unwind (Process &p) {
516514 ProcessLocation location = scopeIP (p);
517515
518516 const Dwarf::CFI *cfi = location.cfi ();
@@ -541,20 +539,20 @@ std::optional<Elf::CoreRegisters> StackFrame::unwind(Process &p) {
541539
542540 // Given the registers available, and the state of the call unwind data,
543541 // calculate the CFA at this point.
544- Elf:: CoreRegisters out;
542+ CoreRegisters out;
545543 switch (dcf.cfaValue .type ) {
546544 case SAME:
547545 case UNDEF:
548546 case ARCH:
549- cfa = Elf::getReg (regs, dcf.cfaReg );
547+ cfa = std::get<gpreg> (regs. getDwarf ( dcf.cfaReg ) );
550548 break ;
551549 case VAL_OFFSET:
552550 case VAL_EXPRESSION:
553551 case REG:
554552 throw (Exception () << " unhandled CFA value type " << dcf.cfaValue .type );
555553
556554 case OFFSET:
557- cfa = Elf::getReg (regs, dcf.cfaReg ) + dcf.cfaValue .u .offset ;
555+ cfa = std::get<gpreg> (regs. getDwarf ( dcf.cfaReg ) ) + dcf.cfaValue .u .offset ;
558556 break ;
559557
560558 case EXPRESSION: {
@@ -567,48 +565,51 @@ std::optional<Elf::CoreRegisters> StackFrame::unwind(Process &p) {
567565 }
568566 default :
569567 cfa = -1 ;
568+ break ;
570569 }
571570 auto rarInfo = dcf.registers .find (cie->rar );
572571
573- for (const auto &entry : dcf.registers ) {
574- const RegisterUnwind &unwind = entry.second ;
575- int regno = entry.first ;
576- try {
577- switch (unwind.type ) {
578- case ARCH:
572+
573+ out = regs;
579574#ifdef CFA_RESTORE_REGNO
580- // "The CFA is defined to be the stack pointer in the calling frame."
581- if (regno == CFA_RESTORE_REGNO)
582- Elf::setReg (out, regno, cfa);
583- else
584- Elf::setReg (out, regno, Elf::getReg (regs, regno));
585- break ;
575+ // "The CFA is defined to be the stack pointer in the calling frame."
576+ out.setDwarf (CFA_RESTORE_REGNO, RegisterValue{cfa} );
586577#endif
587- case UNDEF:
588- case SAME:
589- Elf::setReg (out, regno, Elf::getReg (regs, regno));
590- break ;
591- case OFFSET: // XXX: assume addrLen = sizeof Elf_Addr
592- Elf::setReg ( out, regno, p. io -> readObj <Elf::Addr>(cfa + unwind. u . offset ) );
578+ for ( const auto &[regno, unwind] : dcf. registers ) {
579+ try {
580+ switch (unwind. type ) {
581+ case OFFSET: {
582+ RegisterFromReader rfr (*p. io , cfa + unwind. u . offset );
583+ out. setDwarf ( regno, rfr );
593584 break ;
585+ }
586+
594587 case REG:
595- Elf::setReg ( out, regno, Elf::getReg (out, unwind.u .reg ));
588+ out. setDwarf ( regno, regs. getDwarf ( unwind.u .reg ));
596589 break ;
590+
597591 case VAL_EXPRESSION:
598592 case EXPRESSION: {
599593 ExpressionStack stack;
600594 stack.push (cfa);
601595 DWARFReader reader (cfi->io , unwind.u .expression .offset ,
602596 unwind.u .expression .offset + unwind.u .expression .length );
603- auto val = stack.eval (p, reader, this , location.elfReloc ());
597+ auto val = gpreg ( stack.eval (p, reader, this , location.elfReloc () ));
604598 // EXPRESSIONs give an address, VAL_EXPRESSION gives a literal.
605599 if (unwind.type == EXPRESSION)
606600 p.io ->readObj (val, &val);
607- Elf::setReg ( out, regno, val);
601+ out. setDwarf ( regno, RegisterValue{ val} );
608602 break ;
609603 }
604+
605+ case SAME:
606+ out.setDwarf (regno, regs.getDwarf (regno));
607+ break ;
608+
609+ case ARCH:
610610 default :
611611 break ;
612+
612613 }
613614 }
614615 catch (const Exception &ex) {
@@ -620,13 +621,12 @@ std::optional<Elf::CoreRegisters> StackFrame::unwind(Process &p) {
620621 }
621622
622623 // If the return address isn't defined, then we can't unwind.
623- if (rarInfo == dcf.registers .end () || rarInfo->second .type == UNDEF || cfa == 0 ) {
624+ if (( rarInfo != dcf.registers .end () && rarInfo->second .type == UNDEF) || cfa == 0 ) {
624625 if (p.context .verbose > 1 ) {
625626 *p.context .debug << " DWARF unwinding stopped at "
626627 << std::hex << location.location () << std::dec
627628 << " : " <<
628- (rarInfo == dcf.registers .end () ? " no RAR register found"
629- : rarInfo->second .type == UNDEF ? " RAR register undefined"
629+ (rarInfo == dcf.registers .end () ? " RAR register undefined"
630630 : " null CFA for frame" )
631631 << std::endl;
632632 }
@@ -636,7 +636,7 @@ std::optional<Elf::CoreRegisters> StackFrame::unwind(Process &p) {
636636 // We know the RAR is defined, so make that the instruction pointer in the
637637 // new frame.
638638 if (cie && cie->rar != IPREG)
639- Elf::setReg ( out, IPREG, Elf::getReg ( out, cie->rar ));
639+ out. setDwarf ( IPREG, out. getDwarf ( cie->rar ));
640640 return out;
641641}
642642
0 commit comments