我有一个Elf
类可以读取 Elf 标头并构造各种数据结构;我正在使用mmap
并将文件映射到maddr
上述类中的变量。一个指向这个类的指针被传递给一个DwarfSymTab
类(它依赖于一个Dwarf
对 dwarf 部分进行基本读取的类),但是在这个类的构造函数中,maddr
它的值从它第一次初始化时突然发生了变化。
我正在使用 dbx 来观察这个变化,但是 dbx 抱怨一个变量超出了范围,这是在类中明确定义的。以下是类定义和 dbx 输出的一些摘录。
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
您可以看到指向 Elf 类的指针是完整的,并且maddr
已经以某种方式被丢弃,例如,fd
成员很好(这是正在读取 Elf 数据的文件的 fd ......我有省略了显示这种情况的 dbx 输出,但确实如此)。
谁能解释可能发生的事情?
后记:我已经追踪到“maddr”中对函数调用的变化。这就是 dbx 的显示方式。我首先在下面的函数中停下来,我已经安排将指针作为参数传递给 Elf 类:
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"
此时,指向内存映射区域的指针是正确的。fd 是从中读取 elf 部分的文件的文件:
(dbx) print e, e->fd, e->maddr
e = 0x81b25fc
e->fd = 7
e->maddr = 0xfe6ce000 "^?ELF^A^A^A^F^A"
跳过一些指令:。. .
(dbx) next
stopped in SymTab::read at line 167 in file "symtab.cc"
167 if( error = gethdr(e) )
然后进入读取 dwarf 结构的例程:
(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"
至此,maddr分明已经被踩过,但没有别的了:
(dbx) print e, e->fd, e->maddr
e = 0x81b25fc
e->fd = 7
e->maddr = 0x69727473 "<bad address 0x69727473>"
由于函数调用中没有 malloc'ing(据我所知),这可能是什么原因造成的?DwarfSymTab 类中的“gethdr”覆盖了基础“SymTab”类中的虚函数。我不知道这是否与函数的调用方式有任何关系。
我为细节的数量道歉,但正如我所指出的,这个问题不能真正简化(或者可能超出了我的能力)。
后记:其实情况比这更糟糕的原因有以下几点。确实,通过像上面那样进入 'gethdr' 函数,Elf 类的 'maddr' 成员是不正确的,但是如果我返回堆栈到调用帧,一切都很好:
(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"
这对我来说根本没有任何意义。