0

我有一个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"

这对我来说根本没有任何意义。

4

0 回答 0