mirror of
https://github.com/golang/go
synced 2024-11-24 22:47:58 -07:00
libmach: support reading symbols from Windows .exe for nm
Fixes #979. R=rsc, alex.brainman CC=golang-dev, vcc.163 https://golang.org/cl/4894051
This commit is contained in:
parent
d8333d41f2
commit
eae0a48cf5
@ -142,6 +142,7 @@ enum
|
|||||||
FAMD64B, /* 6.out bootable */
|
FAMD64B, /* 6.out bootable */
|
||||||
FPOWER64, /* 9.out */
|
FPOWER64, /* 9.out */
|
||||||
FPOWER64B, /* 9.out bootable */
|
FPOWER64B, /* 9.out bootable */
|
||||||
|
FWINPE, /* windows PE executable */
|
||||||
|
|
||||||
ANONE = 0, /* dissembler types */
|
ANONE = 0, /* dissembler types */
|
||||||
AMIPS,
|
AMIPS,
|
||||||
|
@ -32,6 +32,11 @@ static char dosstub[] =
|
|||||||
0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Note: currently only up to 8 chars plus \0.
|
||||||
|
static char *symlabels[] = {
|
||||||
|
"symtab", "esymtab", "pclntab", "epclntab"
|
||||||
|
};
|
||||||
|
|
||||||
static Sym *rsrcsym;
|
static Sym *rsrcsym;
|
||||||
|
|
||||||
static char symnames[256];
|
static char symnames[256];
|
||||||
@ -44,6 +49,7 @@ static int pe64;
|
|||||||
static int nsect;
|
static int nsect;
|
||||||
static int nextsectoff;
|
static int nextsectoff;
|
||||||
static int nextfileoff;
|
static int nextfileoff;
|
||||||
|
static int textsect;
|
||||||
|
|
||||||
static IMAGE_FILE_HEADER fh;
|
static IMAGE_FILE_HEADER fh;
|
||||||
static IMAGE_OPTIONAL_HEADER oh;
|
static IMAGE_OPTIONAL_HEADER oh;
|
||||||
@ -449,20 +455,29 @@ addsymtable(void)
|
|||||||
{
|
{
|
||||||
IMAGE_SECTION_HEADER *h;
|
IMAGE_SECTION_HEADER *h;
|
||||||
int i, size;
|
int i, size;
|
||||||
|
Sym *s;
|
||||||
|
|
||||||
if(nextsymoff == 0)
|
fh.NumberOfSymbols = sizeof(symlabels)/sizeof(symlabels[0]);
|
||||||
return;
|
size = nextsymoff + 4 + 18*fh.NumberOfSymbols;
|
||||||
|
|
||||||
size = nextsymoff + 4 + 18;
|
|
||||||
h = addpesection(".symtab", size, size);
|
h = addpesection(".symtab", size, size);
|
||||||
h->Characteristics = IMAGE_SCN_MEM_READ|
|
h->Characteristics = IMAGE_SCN_MEM_READ|
|
||||||
IMAGE_SCN_MEM_DISCARDABLE;
|
IMAGE_SCN_MEM_DISCARDABLE;
|
||||||
chksectoff(h, cpos());
|
chksectoff(h, cpos());
|
||||||
fh.PointerToSymbolTable = cpos();
|
fh.PointerToSymbolTable = cpos();
|
||||||
fh.NumberOfSymbols = 1;
|
|
||||||
strnput("", 18); // one empty symbol
|
// put COFF symbol table
|
||||||
// put symbol string table
|
for (i=0; i<fh.NumberOfSymbols; i++) {
|
||||||
lputl(size);
|
s = rlookup(symlabels[i], 0);
|
||||||
|
strnput(s->name, 8);
|
||||||
|
lputl(datoff(s->value));
|
||||||
|
wputl(textsect);
|
||||||
|
wputl(0x0308); // "array of structs"
|
||||||
|
cput(2); // storage class: external
|
||||||
|
cput(0); // no aux entries
|
||||||
|
}
|
||||||
|
|
||||||
|
// put COFF string table
|
||||||
|
lputl(nextsymoff + 4);
|
||||||
for (i=0; i<nextsymoff; i++)
|
for (i=0; i<nextsymoff; i++)
|
||||||
cput(symnames[i]);
|
cput(symnames[i]);
|
||||||
strnput("", h->SizeOfRawData - size);
|
strnput("", h->SizeOfRawData - size);
|
||||||
@ -532,6 +547,7 @@ asmbpe(void)
|
|||||||
IMAGE_SCN_CNT_INITIALIZED_DATA|
|
IMAGE_SCN_CNT_INITIALIZED_DATA|
|
||||||
IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ;
|
IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ;
|
||||||
chksectseg(t, &segtext);
|
chksectseg(t, &segtext);
|
||||||
|
textsect = nsect;
|
||||||
|
|
||||||
d = addpesection(".data", segdata.len, segdata.filelen);
|
d = addpesection(".data", segdata.len, segdata.filelen);
|
||||||
d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
|
d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|
|
||||||
|
@ -66,6 +66,7 @@ static int adotout(int, Fhdr*, ExecHdr*);
|
|||||||
static int elfdotout(int, Fhdr*, ExecHdr*);
|
static int elfdotout(int, Fhdr*, ExecHdr*);
|
||||||
static int machdotout(int, Fhdr*, ExecHdr*);
|
static int machdotout(int, Fhdr*, ExecHdr*);
|
||||||
static int armdotout(int, Fhdr*, ExecHdr*);
|
static int armdotout(int, Fhdr*, ExecHdr*);
|
||||||
|
static int pedotout(int, Fhdr*, ExecHdr*);
|
||||||
static void setsym(Fhdr*, vlong, int32, vlong, int32, vlong, int32);
|
static void setsym(Fhdr*, vlong, int32, vlong, int32, vlong, int32);
|
||||||
static void setdata(Fhdr*, uvlong, int32, vlong, int32);
|
static void setdata(Fhdr*, uvlong, int32, vlong, int32);
|
||||||
static void settext(Fhdr*, uvlong, uvlong, int32, vlong);
|
static void settext(Fhdr*, uvlong, uvlong, int32, vlong);
|
||||||
@ -312,6 +313,15 @@ ExecTable exectab[] =
|
|||||||
sizeof(Exec),
|
sizeof(Exec),
|
||||||
beswal,
|
beswal,
|
||||||
common },
|
common },
|
||||||
|
{ 0x4d5a9000, /* see dosstub[] in pe.c */
|
||||||
|
"windows PE executable",
|
||||||
|
nil,
|
||||||
|
FWINPE,
|
||||||
|
0,
|
||||||
|
&mi386,
|
||||||
|
sizeof(Exec), /* TODO */
|
||||||
|
nil,
|
||||||
|
pedotout },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1249,6 +1259,164 @@ armdotout(int fd, Fhdr *fp, ExecHdr *hp)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structures needed to parse PE image.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint16 Machine;
|
||||||
|
uint16 NumberOfSections;
|
||||||
|
uint32 TimeDateStamp;
|
||||||
|
uint32 PointerToSymbolTable;
|
||||||
|
uint32 NumberOfSymbols;
|
||||||
|
uint16 SizeOfOptionalHeader;
|
||||||
|
uint16 Characteristics;
|
||||||
|
} IMAGE_FILE_HEADER;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8 Name[8];
|
||||||
|
uint32 VirtualSize;
|
||||||
|
uint32 VirtualAddress;
|
||||||
|
uint32 SizeOfRawData;
|
||||||
|
uint32 PointerToRawData;
|
||||||
|
uint32 PointerToRelocations;
|
||||||
|
uint32 PointerToLineNumbers;
|
||||||
|
uint16 NumberOfRelocations;
|
||||||
|
uint16 NumberOfLineNumbers;
|
||||||
|
uint32 Characteristics;
|
||||||
|
} IMAGE_SECTION_HEADER;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32 VirtualAddress;
|
||||||
|
uint32 Size;
|
||||||
|
} IMAGE_DATA_DIRECTORY;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16 Magic;
|
||||||
|
uint8 MajorLinkerVersion;
|
||||||
|
uint8 MinorLinkerVersion;
|
||||||
|
uint32 SizeOfCode;
|
||||||
|
uint32 SizeOfInitializedData;
|
||||||
|
uint32 SizeOfUninitializedData;
|
||||||
|
uint32 AddressOfEntryPoint;
|
||||||
|
uint32 BaseOfCode;
|
||||||
|
uint32 BaseOfData;
|
||||||
|
uint32 ImageBase;
|
||||||
|
uint32 SectionAlignment;
|
||||||
|
uint32 FileAlignment;
|
||||||
|
uint16 MajorOperatingSystemVersion;
|
||||||
|
uint16 MinorOperatingSystemVersion;
|
||||||
|
uint16 MajorImageVersion;
|
||||||
|
uint16 MinorImageVersion;
|
||||||
|
uint16 MajorSubsystemVersion;
|
||||||
|
uint16 MinorSubsystemVersion;
|
||||||
|
uint32 Win32VersionValue;
|
||||||
|
uint32 SizeOfImage;
|
||||||
|
uint32 SizeOfHeaders;
|
||||||
|
uint32 CheckSum;
|
||||||
|
uint16 Subsystem;
|
||||||
|
uint16 DllCharacteristics;
|
||||||
|
uint32 SizeOfStackReserve;
|
||||||
|
uint32 SizeOfStackCommit;
|
||||||
|
uint32 SizeOfHeapReserve;
|
||||||
|
uint32 SizeOfHeapCommit;
|
||||||
|
uint32 LoaderFlags;
|
||||||
|
uint32 NumberOfRvaAndSizes;
|
||||||
|
IMAGE_DATA_DIRECTORY DataDirectory[16];
|
||||||
|
} IMAGE_OPTIONAL_HEADER;
|
||||||
|
|
||||||
|
static int
|
||||||
|
match8(void *buf, char *cmp)
|
||||||
|
{
|
||||||
|
return strncmp((char*)buf, cmp, 8) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO(czaplinski): 64b windows? */
|
||||||
|
/*
|
||||||
|
* Read from Windows PE/COFF .exe file image.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
pedotout(int fd, Fhdr *fp, ExecHdr *hp)
|
||||||
|
{
|
||||||
|
uint32 start, magic;
|
||||||
|
uint32 symtab, esymtab;
|
||||||
|
IMAGE_FILE_HEADER fh;
|
||||||
|
IMAGE_SECTION_HEADER sh;
|
||||||
|
IMAGE_OPTIONAL_HEADER oh;
|
||||||
|
uint8 sym[18];
|
||||||
|
uint32 *valp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
USED(hp);
|
||||||
|
seek(fd, 0x3c, 0);
|
||||||
|
if (readn(fd, &start, sizeof(start)) != sizeof(start)) {
|
||||||
|
werrstr("crippled PE MSDOS header");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
start = leswal(start);
|
||||||
|
|
||||||
|
seek(fd, start, 0);
|
||||||
|
if (readn(fd, &magic, sizeof(magic)) != sizeof(magic)) {
|
||||||
|
werrstr("no PE magic number found");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (beswal(magic) != 0x50450000) { /* "PE\0\0" */
|
||||||
|
werrstr("incorrect PE magic number");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readn(fd, &fh, sizeof(fh)) != sizeof(fh)) {
|
||||||
|
werrstr("crippled PE File Header");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (fh.PointerToSymbolTable == 0) {
|
||||||
|
werrstr("zero pointer to COFF symbol table");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readn(fd, &oh, sizeof(oh)) != sizeof(oh)) {
|
||||||
|
werrstr("crippled PE Optional Header");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
seek(fd, start+sizeof(magic)+sizeof(fh)+leswab(fh.SizeOfOptionalHeader), 0);
|
||||||
|
fp->txtaddr = fp->dataddr = 0;
|
||||||
|
for (i=0; i<leswab(fh.NumberOfSections); i++) {
|
||||||
|
if (readn(fd, &sh, sizeof(sh)) != sizeof(sh)) {
|
||||||
|
werrstr("could not read Section Header %d", i+1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (match8(sh.Name, ".text"))
|
||||||
|
settext(fp, leswal(sh.VirtualAddress), leswal(oh.AddressOfEntryPoint), leswal(sh.VirtualSize), leswal(sh.PointerToRawData));
|
||||||
|
if (match8(sh.Name, ".data"))
|
||||||
|
setdata(fp, leswal(sh.VirtualAddress), leswal(sh.SizeOfRawData), leswal(sh.PointerToRawData), leswal(sh.VirtualSize)-leswal(sh.SizeOfRawData));
|
||||||
|
}
|
||||||
|
if (fp->txtaddr==0 || fp->dataddr==0) {
|
||||||
|
werrstr("no .text or .data");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
seek(fd, leswal(fh.PointerToSymbolTable), 0);
|
||||||
|
symtab = esymtab = 0;
|
||||||
|
for (i=0; i<leswal(fh.NumberOfSymbols); i++) {
|
||||||
|
if (readn(fd, &sym, sizeof(sym)) != sizeof(sym)) {
|
||||||
|
werrstr("crippled COFF symbol %d", i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
valp = (uint32 *)&sym[8];
|
||||||
|
if (match8(sym, "symtab"))
|
||||||
|
symtab = leswal(*valp);
|
||||||
|
if (match8(sym, "esymtab"))
|
||||||
|
esymtab = leswal(*valp);
|
||||||
|
}
|
||||||
|
if (symtab==0 || esymtab==0) {
|
||||||
|
werrstr("no symtab or esymtab in COFF symbol table");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
setsym(fp, symtab, esymtab-symtab, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
settext(Fhdr *fp, uvlong e, uvlong a, int32 s, vlong off)
|
settext(Fhdr *fp, uvlong e, uvlong a, int32 s, vlong off)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user