I have an Elf
class which reads in Elf headers and constructs various data structures; I am using mmap
and mmap the file to a variable maddr
in the above class. A pointer to this class is passed to a DwarfSymTab
class (which relies on a Dwarf
class which does the basic read of dwarf sections) but in the constructor for this class, maddr
has suddenly changed in value from when it was first initialized.
I am using dbx to watch this change, but dbx is complaining about a variable out of scope which is quite definitely defined in the class. Following are some extracts of the class definitions and the dbx output.
class Elf {
friend class DwarfSymTab;
friend class SymTab;
friend class Dwarf;
friend class HostFunc;
int fd;
ElfEhdr ehdr;
ElfEhdr *h;
uchar magic[4];
ElfSect *symtab;
ElfSect *symstr;
ElfSect *dynsym;
ElfSect *dynstr;
ElfSect *bss;
ulong dynamic;
struct stat st;
uchar *maddr;
. . .
};
class DwarfSymTab : public SymTab {
private:
Elf *elf;
Dwarf *dwarf;
DwarfRec *r;
DwarfUType *dt;
DwarfLine *dline;
MemLayout memlayout;
. . .
};
Localproc *HostFunc::coreopen(int corefd, int stabfd){
. . .
e[STAB] = new Elf();
if(e[STAB]->fdopen(stabfd) < 0){
fprintf(stderr, "Elf::open: %s\n", e[STAB]->perror());
exit(1);
}
stopped in HostFunc::coreopen at line 858 in file "hostfunc.cc"
858 e[CORE] = new Elf();
(dbx) print e[0], e[0]->maddr
e[0] = 0x81b26bc
e[0]->maddr = 0xfe6ce000 "^?ELF^A^A^A^F^A"
DwarfSymTab::DwarfSymTab(Core* c, Elf *e, SymTab *i, long reloc)
:SymTab(c, e, i, reloc) {
elf = e;
r = new DwarfRec;
}
stopped in DwarfSymTab::DwarfSymTab at line 30 in file "dwarfsymtab.cc"
30 elf = e;
(dbx) next
stopped in DwarfSymTab::DwarfSymTab at line 31 in file "dwarfsymtab.cc"
31 r = new DwarfRec;
(dbx) print e, e->maddr
e = 0x81b26bc
e->maddr = 0x69727473 "<bad address 0x69727473>"
(dbx) print elf
dbx: "elf" is not defined in the scope `pi`dwarfsymtab.cc`DwarfSymTab::DwarfSymTab(Core*,Elf*,SymTab*,long)`
(dbx) print e->fd
e->fd = 6
You can see that the pointer to the Elf class is in tact, and that maddr
has been trashed in some way while for example, the fd
member is fine (this is the fd of the file from which Elf data is being read ... I have omitted the dbx output showing this to be the case but it is so).
Can anyone explain what might be going on?
Postscript: I have tracked down the change in 'maddr' to a call to a function. This is how dbx shows it. I first stop in the following function, and I've arranged to pass the pointer to the Elf class as an argument:
void SymTab::read(Elf *e){
const char *error;
trace( "%d.read()", this ); VOK;
trace( "symtab modified %d", modtime() );
_root = 0;
if( error = gethdr(e) )
_warn = sf( "symbol table header: %s; go on", error );
stopped in SymTab::read at line 164 in file "symtab.cc"
164 trace( "%d.read()", this ); VOK;
(dbx) where
=>[1] SymTab::read(this = 0x81b757c, e = 0x81b25fc), line 164 in "symtab.cc"
[2] HostCore::open(this = 0x81b24a0), line 512 in "hostcore.cc"
[3] HostProcess::open(this = 0x81b1c24, ischild = 0), line 318 in "hostcore.cc"
[4] TermAction(parent = 0x818b294, obj = 0x81b1c24, pick = 0), line 160 in "term.cc"
[5] TermServe(), line 238 in "term.cc"
[6] PadsServe(n = 0), line 292 in "term.cc"
[7] main(argc = 1, av = 0xfeffdd68), line 75 in "pi.cc"
At this point, the pointer to the memory-mapped region is correct. The fd is that of the file from which elf sections are being read:
(dbx) print e, e->fd, e->maddr
e = 0x81b25fc
e->fd = 7
e->maddr = 0xfe6ce000 "^?ELF^A^A^A^F^A"
Stepping over a few instructions: . . .
(dbx) next
stopped in SymTab::read at line 167 in file "symtab.cc"
167 if( error = gethdr(e) )
and then stepping into the routine which reads the dwarf structures:
(dbx) step
stopped in DwarfSymTab::gethdr at line 36 in file "dwarfsymtab.cc"
36 switch(elf->encoding()){
(dbx) where
=>[1] DwarfSymTab::gethdr(this = 0x81b757c, e = 0x81b25fc), line 36 in "dwarfsymtab.cc"
[2] SymTab::read(this = 0x81b757c, e = 0x81b25fc), line 167 in "symtab.cc"
[3] HostCore::open(this = 0x81b24a0), line 512 in "hostcore.cc"
[4] HostProcess::open(this = 0x81b1c24, ischild = 0), line 318 in "hostcore.cc"
[5] TermAction(parent = 0x818b294, obj = 0x81b1c24, pick = 0), line 160 in "term.cc"
[6] TermServe(), line 238 in "term.cc"
[7] PadsServe(n = 0), line 292 in "term.cc"
[8] main(argc = 1, av = 0xfeffdd68), line 75 in "pi.cc"
At this point, maddr has clearly been trampled on, but nothing else:
(dbx) print e, e->fd, e->maddr
e = 0x81b25fc
e->fd = 7
e->maddr = 0x69727473 "<bad address 0x69727473>"
Since there is no malloc'ing going on across a function call (as far as I know), what could be causing this? 'gethdr' in the DwarfSymTab class is overrinding a virtual function in the base 'SymTab' class. I don't know if this has any bearing on how the function is called.
I apologize for the amount of detail, but as I pointed out, the problem can't be really simplified (or perhaps it's beyond my abilities).
Post-postscript: In fact the situation is worse than this because of the following. It is true that by stepping into the 'gethdr' function as above, the 'maddr' member of the Elf class is incorrect, but if I go back down the stack to the calling frame, everything is fine:
(dbx) next
stopped in SymTab::read at line 167 in file "symtab.cc"
167 if( error = gethdr(e) )
(dbx) step
stopped in DwarfSymTab::gethdr at line 36 in file "dwarfsymtab.cc"
36 switch(elf->encoding()){
(dbx) print e, e->fd, e->maddr
e = 0x81b25fc
e->fd = 7
e->maddr = 0x69727473 "<bad address 0x69727473>"
(dbx) up
Current function is SymTab::read
167 if( error = gethdr(e) )
(dbx) print e, e->fd, e->maddr
e = 0x81b25fc
e->fd = 7
e->maddr = 0xfe6ce000 "^?ELF^A^A^A^F^A"
This simply doesn't make any sense to me.