On 2/3/20 10:15 PM, enh wrote:
> On Tue, Jan 28, 2020 at 7:11 PM Rob Landley <[email protected]> wrote:
>>
>> Is reading 64 bit binaries from 32 bit systems interesting? Because struct sh
>> and struct ph have "int" and "long" values, which are the same on 32 bit.
>> (long long is the one that's always 64 bit.)
>
> i certainly intended to support that combination. i've actually since
> added CTS tests that use `readelf -S` output, but obviously not on
> files with values big enough to break this.
$ git diff toys/*/readelf.c | diffstat
readelf.c | 330 +++++++++++++++++++++++++++++++-------------------------------
1 file changed, 166 insertions(+), 164 deletions(-)
But I got distracted by $DAYJOB before finishing.
> i've sent the obvious patch.
>
>> Last elf plumbing I did (file?) I carefully made sure every access wouldn't
>> go
>> off the end of the mmap. This doesn't seem to ever check that? (ph.filesz
>> could
>> be zero then you're feeding -1 to printf, etc...)
>
> like i said, i haven't fuzzed this at all, so there's doubtless _some_
> checks missing. and, yes, that seems to be one. (and a sign [no pun
> intended] that all this should be switched to unsigned.) i'll send a
> patch for that tomorrow night if you haven't already done it by then.
I've learned my lesson not to try cleaning up commands until the submitter is
done with them. My bad for starting early this time...
I deleted my changes so I could apply yours. (Attached in case you're curious,
but otherwise I'm sticking to shell stuff this release.)
> anywhere there's a dereference should be protected: search for
> references to TT.size. there aren't as many as you might expect to see
> because get_sh() and get_ph() won't return a bad section or program
> header.
I was mostly converting it to auto-advancing elf_get(char **pos, int len) with
elf_int() and elf_long() wrappers on top of that to handle the 4 and 8 byte
common cases. (There were a few 2 bytes, and the rest were *ll++.)
That way it didn't have to do the traversal math multiple times in parallel by
hand. With that and a str_eat() function that was like strstart requiring a full
match and rounding up to 4 I think I had most of it converted over. (Which
avoided a function pointer in the globals...)
>> Should work on non-pathological ELF files, of course... :)
>
> sadly i didn't test with chrome's .so files or i'd have caught this :-)
*shrug* I hadn't gotten to a point where it compiled again yet, I was just
reading the code...
Rob
diff --git a/toys/pending/readelf.c b/toys/pending/readelf.c
index a955426..c54a00a 100644
--- a/toys/pending/readelf.c
+++ b/toys/pending/readelf.c
@@ -10,7 +10,7 @@ config READELF
bool "readelf"
default y
help
- usage: readelf [-adhlnSsW] [-p SECTION] [-x SECTION] [file...]
+ usage: readelf [-adhlnSs] [-p SECTION] [-x SECTION] [file...]
Displays information about ELF files.
@@ -22,7 +22,6 @@ config READELF
-p S Dump strings found in named/numbered section
-S Show section headers
-s Show symbol tables (.dynsym and .symtab)
- -W Don't truncate fields (default in toybox)
-x S Hex dump of named/numbered section
--dyn-syms Show just .dynsym symbol table
@@ -36,8 +35,7 @@ GLOBALS(
char *elf, *shstrtab, *f;
long long shoff, phoff, size;
- int bits, shnum, shentsize, phentsize;
- int64_t (*elf_int)(void *ptr, unsigned size);
+ int bits, endian, shnum, shentsize, phentsize;
)
// Section header.
@@ -53,30 +51,50 @@ struct ph {
long offset, vaddr, paddr, filesz, memsz, align;
};
-static void get_sh(int i, struct sh *s)
+static long long elf_get(char **pos, int len)
{
- char *shdr = TT.elf+TT.shoff+i*TT.shentsize;
+ long long rc = ((TT.endian == 2) ? peek_be : peek_le)(*pos, len);
- if (i >= TT.shnum || shdr > TT.elf+TT.size-TT.shentsize) {
- error_exit("%s: bad shdr %d",TT.f,i);
- }
+ *pos += len;
- s->type = TT.elf_int(shdr+4, 4);
- s->flags = TT.elf_int(shdr+8, 4*(TT.bits+1));
- s->addr = TT.elf_int(shdr+8+4*(TT.bits+1), 4*(TT.bits+1));
- s->offset = TT.elf_int(shdr+8+8*(TT.bits+1), 4*(TT.bits+1));
- s->size = TT.elf_int(shdr+8+12*(TT.bits+1), 4*(TT.bits+1));
- s->link = TT.elf_int(shdr+8+16*(TT.bits+1), 4);
- s->info = TT.elf_int(shdr+12+16*(TT.bits+1), 4);
- s->addralign = TT.elf_int(shdr+16+16*(TT.bits+1), 4*(TT.bits+1));
- s->entsize = TT.elf_int(shdr+16+20*(TT.bits+1), 4*(TT.bits+1));
+ return rc;
+}
+
+static long long elf_int(char **pos)
+{
+ return elf_get(pos, 4);
+}
+
+static long long elf_long(char **pos)
+{
+ return elf_get(pos, 4*(TT.bits+1));
+}
+
+static void get_sh(int i, struct sh *s)
+{
+ char *shdr = TT.elf+TT.shoff+i*TT.shentsize;
+ int off;
+
+ if (i >= TT.shnum || shdr > TT.elf+TT.size-TT.shentsize)
+ error_exit("%s: bad shdr %d", TT.f, i);
+
+ off = elf_int(&shdr);
+ s->type = elf_int(&shdr);
+ s->flags = elf_long(&shdr);
+ s->addr = elf_long(&shdr);
+ s->offset = elf_long(&shdr);
+ s->size = elf_long(&shdr);
+ s->link = elf_int(&shdr);
+ s->info = elf_int(&shdr);
+ s->addralign = elf_long(&shdr);
+ s->entsize = elf_long(&shdr);
if (!TT.shstrtab) s->name = "?";
else {
- s->name = TT.shstrtab + TT.elf_int(shdr, 4);
- if (s->name >= TT.elf+TT.size) error_exit("%s: bad shdr name %d",TT.f,i);
+ s->name = TT.shstrtab + off;
+ if (s->name >= TT.elf+TT.size) error_exit("%s: bad shdr name %d", TT.f, i);
if (s->offset >= TT.size-s->size && s->type != 8 /*SHT_NOBITS*/)
- error_exit("%s: bad section %d",TT.f,i);
+ error_exit("%s: bad section %d", TT.f, i);
}
}
@@ -100,34 +118,27 @@ static int find_section(char *spec, struct sh *s)
}
error_msg("%s: no section '%s", TT.f, spec);
+
return 0;
}
static void get_ph(int i, struct ph *ph)
{
char *phdr = TT.elf+TT.phoff+i*TT.phentsize;
+ long long (*get)(char **pos) = TT.bits ? elf_long : elf_int;
- if (phdr > TT.elf+TT.size-TT.phentsize) error_exit("%s: bad phdr %d",TT.f,i);
+ if (phdr > TT.elf+TT.size-TT.phentsize) error_exit("%s: bad phdr %d", TT.f,i);
// Elf64_Phdr reordered fields.
- ph->type = TT.elf_int(phdr, 4);
- if (TT.bits) {
- ph->flags = TT.elf_int(phdr+=4, 4);
- ph->offset = TT.elf_int(phdr+=4, 8);
- ph->vaddr = TT.elf_int(phdr+=8, 8);
- ph->paddr = TT.elf_int(phdr+=8, 8);
- ph->filesz = TT.elf_int(phdr+=8, 8);
- ph->memsz = TT.elf_int(phdr+=8, 8);
- ph->align = TT.elf_int(phdr+=8, 8);
- } else {
- ph->offset = TT.elf_int(phdr+=4, 4);
- ph->vaddr = TT.elf_int(phdr+=4, 4);
- ph->paddr = TT.elf_int(phdr+=4, 4);
- ph->filesz = TT.elf_int(phdr+=4, 4);
- ph->memsz = TT.elf_int(phdr+=4, 4);
- ph->flags = TT.elf_int(phdr+=4, 4);
- ph->align = TT.elf_int(phdr+=4, 4);
- }
+ ph->type = elf_int(&phdr);
+ if (TT.bits) ph->flags = elf_int(&phdr);
+ ph->offset = get(&phdr);
+ ph->vaddr = get(&phdr);
+ ph->paddr = get(&phdr);
+ ph->filesz = get(&phdr);
+ ph->memsz = get(&phdr);
+ if (!TT.bits) ph->flags = elf_int(&phdr);
+ ph->align = get(&phdr);
}
#define MAP(...) __VA_ARGS__
@@ -200,33 +211,31 @@ DECODER(stv_type, MAP({{0,"DEFAULT"},{1,"INTERNAL"},{2,"HIDDEN"},
static void show_symbols(struct sh *table, struct sh *strtab)
{
char *symtab = TT.elf+table->offset, *ndx;
- int sym_size = (TT.bits ? 24 : 16), numsym = table->size/sym_size, i;
+ int numsym = table->size/(TT.bits ? 24 : 16), i;
- if (numsym == 0) return;
+ if (!numsym) return;
- xputc('\n');
- printf("Symbol table '%s' contains %d entries:\n"
+ printf("\nSymbol table '%s' contains %d entries:\n"
" Num: %*s Size Type Bind Vis Ndx Name\n",
table->name, numsym, 5+8*TT.bits, "Value");
- for (i=0; i<numsym; i++) {
- int st_name = TT.elf_int(symtab, 4), st_value, st_shndx;
- unsigned char st_info, st_other;
- long st_size;
- char *name;
+ for (i = 0; i<numsym; i++) {
+ char st_info, st_other, *name, buf[8];
+ int st_name = elf_int(&symtab), st_value, st_shndx;
+ long long st_size;
// The various fields were moved around for 64-bit.
if (TT.bits) {
- st_info = symtab[4];
- st_other = symtab[5];
- st_shndx = TT.elf_int(symtab+6, 2);
- st_value = TT.elf_int(symtab+8, 8);
- st_size = TT.elf_int(symtab+16, 8);
+ st_info = *symtab++;
+ st_other = *symtab++;
+ st_shndx = elf_get(&symtab, 2);
+ st_value = elf_long(&symtab);
+ st_size = elf_long(&symtab);
} else {
- st_value = TT.elf_int(symtab+4, 4);
- st_size = TT.elf_int(symtab+8, 4);
- st_info = symtab[12];
- st_other = symtab[13];
- st_shndx = TT.elf_int(symtab+14, 2);
+ st_value = elf_int(&symtab);
+ st_size = elf_int(&symtab);
+ st_info = *symtab++;
+ st_other = *symtab++;
+ st_shndx = elf_get(&symtab, 2);
}
name = TT.elf + strtab->offset + st_name;
@@ -234,58 +243,68 @@ static void show_symbols(struct sh *table, struct sh *strtab)
if (!st_shndx) ndx = "UND";
else if (st_shndx==0xfff1) ndx = "ABS";
- else sprintf(ndx = toybuf, "%d", st_shndx);
+ else sprintf(ndx = buf, "%d", st_shndx);
// TODO: look up and show any symbol versions with @ or @@.
- printf("%6d: %0*x %5ld %-7s %-6s %-9s%3s %s\n", i, 8*(TT.bits+1),
+ printf("%6d: %0*x %5lld %-7s %-6s %-9s%3s %s\n", i, 8*(TT.bits+1),
st_value, st_size, stt_type(st_info & 0xf), stb_type(st_info >> 4),
stv_type(st_other & 3), ndx, name);
- symtab += sym_size;
}
}
+// like strstart but require full match and round up advance to 4
+static int streat(char **a, char *b)
+{
+ int len = strlen(b)+1;
+
+ if (strcmp(*a, b)) return 0;
+ *a += (len+3)&~3;
+
+ return 1;
+}
+
static void show_notes(long offset, long size)
{
- char *note = TT.elf + offset;
+ char *note = TT.elf + offset, *next;
- printf(" %-20s %10s\tDescription\n", "Owner", "Data size");
- while (note < TT.elf+offset+size) {
- int namesz = TT.elf_int(note, 4), descsz = TT.elf_int(note+4, 4),
- type = TT.elf_int(note+8, 4), j = 0;
- char *name = note+12;
+ printf(" %-20s Data size\tDescription\n", "Owner");
+ for (note = TT.elf+offset; note < TT.elf+offset+size; note = next) {
+ int namesz = elf_int(¬e), descsz = elf_int(¬e), type = elf_int(¬e);
- printf(" %-20.*s 0x%08x\t", namesz, name, descsz);
- if (!memcmp(name, "GNU", 4)) {
+ next = note + ((descsz+3)&~3)+((namesz+3)&~3);
+ printf(" %-20.*s 0x%08x\t", namesz, note, descsz);
+ if (streat(¬e, "GNU")) {
if (type == 1) {
+ int a = elf_int(¬e), b = elf_int(¬e), c = elf_int(¬e);
+
printf("NT_GNU_ABI_TAG\tOS: %s, ABI: %d.%d.%d",
- !TT.elf_int(note+16, 4)?"Linux":"?",
- (int)TT.elf_int(note+20, 4), (int)TT.elf_int(note+24, 4),
- (int)TT.elf_int(note+28, 4)), j=1;
+ a?"?":"Linux", b, c, (int)elf_int(¬e));
} else if (type == 3) {
printf("NT_GNU_BUILD_ID\t");
- for (;j<descsz;j++) printf("%02x",note[16+j]);
- } else if (type == 4) {
- printf("NT_GNU_GOLD_VERSION\t%.*s", descsz, note+16), j=1;
- }
- } else if (!memcmp(name, "Android", 8)) {
- if (type == 1) {
- printf("NT_VERSION\tAPI level %d", (int)TT.elf_int(note+20, 4)), j=1;
- if (descsz>=132) printf(", NDK %.64s (%.64s)",note+24,note+24+64);
+ for (type = 0; type<descsz; type++) printf("%02x", *note++);
+ } else if (type == 4)
+ printf("NT_GNU_GOLD_VERSION\t%.*s", descsz, note);
+ else {
+ note -= 4;
+ goto dump;
}
- } else if (!memcmp(name, "CORE", 5) || !memcmp(name, "LINUX", 6)) {
+ } else if (!strcmp(name, "Android") && type == 1) {
+ printf("NT_VERSION\tAPI level %d", (int)elf_int(¬e)), j=1;
+ if (descsz>=132) printf(", NDK %.64s (%.64s)", note, note+64);
+ } else if (streat(name, "CORE") || !memcmp(name, "LINUX", 6)) {
char *desc = *name=='C' ? nt_type_core(type) : nt_type_linux(type);
- if (*desc != '0') printf("%s", desc), j=1;
- }
-
- // If we didn't do custom output above, show a hex dump.
- if (!j) {
+ if (*desc != '0') printf("%s", desc);
+ else goto dump;
+ } else {
+dump:
printf("0x%x\t", type);
- for (;j<descsz;j++) printf("%c%02x",!j?'\t':' ',note[16+j]);
+ for (type = 0;type<descsz;type++) printf("%c%02x",!j?'\t':' ',note[16+j]);
}
xputc('\n');
+murgle
note += 3*4 + ((namesz+3)&~3) + ((descsz+3)&~3);
}
}
@@ -296,51 +315,47 @@ static void scan_elf()
symtab = {}, s;
struct ph ph;
int endian, version, elf_type, flags, entry, ehsize, phnum, shstrndx, i,j,w;
-
- if (TT.size < 45 || memcmp(TT.elf, "\177ELF", 4)) {
- error_msg("%s: not ELF", TT.f);
- return;
- }
-
- TT.bits = TT.elf[4] - 1;
- endian = TT.elf[5];
- version = TT.elf[6];
- TT.elf_int = (endian==2) ? peek_be : peek_le;
- if (TT.bits < 0 || TT.bits > 1 || endian < 1 || endian > 2 || version != 1) {
- error_msg("%s: bad ELF", TT.f);
- return;
- }
-
- elf_type = TT.elf_int(TT.elf+16, 2);
- entry = TT.elf_int(TT.elf+24, 4+4*TT.bits);
- TT.phoff = TT.elf_int(TT.elf+28+4*TT.bits, 4+4*TT.bits);
- TT.shoff = TT.elf_int(TT.elf+32+8*TT.bits, 4+4*TT.bits);
- flags = TT.elf_int(TT.elf+36+12*TT.bits, 4);
- ehsize = TT.elf_int(TT.elf+40+12*TT.bits, 2);
- TT.phentsize = TT.elf_int(TT.elf+42+12*TT.bits, 2);
- phnum = TT.elf_int(TT.elf+44+12*TT.bits, 2);
- TT.shentsize = TT.elf_int(TT.elf+46+12*TT.bits, 2);
- TT.shnum = TT.elf_int(TT.elf+48+12*TT.bits, 2);
- shstrndx = TT.elf_int(TT.elf+50+12*TT.bits, 2);
+ char *elf = TT.elf;
+
+ if (TT.size < 45 || !strstart(&elf, "\177ELF"))
+ return error_msg("%s: not ELF", TT.f);
+
+ TT.bits = (*elf++)-1;
+ TT.endian = *elf++;
+ version = *elf++;
+ if (TT.bits<0 || TT.bits>1 || TT.endian<1 || TT.endian>2 || version!=1)
+ return error_msg("%s: bad ELF", TT.f);
+
+ elf += 9;
+ elf_type = elf_get(&elf, 2);
+ elf += 6;
+ entry = elf_long(&elf);
+ TT.phoff = elf_long(&elf);
+ TT.shoff = elf_long(&elf);
+ flags = elf_int(&elf, 4);
+ ehsize = elf_get(&elf, 2);
+ TT.phentsize = elf_get(&elf, 2);
+ phnum = elf_get(&elf, 2);
+ TT.shentsize = elf_get(&elf, 2);
+ TT.shnum = elf_get(&elf, 2);
+ shstrndx = elf_get(&elf, 2);
// Set up the section header string table so we can use section header names.
// Core files have shstrndx == 0.
TT.shstrtab = 0;
- if (shstrndx != 0) {
+ if (shstrndx) {
get_sh(shstrndx, &shstr);
- if (shstr.type != 3 /*SHT_STRTAB*/) {
- error_msg("%s: bad shstrndx", TT.f);
- return;
- }
+ if (shstr.type != 3 /* SHT_STRTAB */)
+ return error_msg("%s: bad shstrndx", TT.f);
TT.shstrtab = TT.elf+shstr.offset;
}
if (toys.optc > 1) printf("\nFile: %s\n", TT.f);
if (FLAG(h)) {
- printf("ELF Header:\n");
- printf(" Magic: ");
- for (i=0; i<16; i++) printf("%02x%c", TT.elf[i], i==15?'\n':' ');
+ printf("ELF Header:\n Magic: ");
+ for (i=0; i<16; i++) printf(" %02x"+!i, TT.elf[i]);
+ xputc('\n');
printf(" Class: ELF%d\n", TT.bits?64:32);
printf(" Data: 2's complement, %s endian\n",
(endian==2)?"big":"little");
@@ -348,10 +363,10 @@ static void scan_elf()
printf(" OS/ABI: %s\n", os_abi(TT.elf[7]));
printf(" ABI Version: %d\n", TT.elf[8]);
printf(" Type: %s\n", et_type(elf_type));
+ elf = TT.elf+18;
printf(" Machine: %s\n",
- elf_arch_name(TT.elf_int(TT.elf+18, 2)));
- printf(" Version: 0x%x\n",
- (int) TT.elf_int(TT.elf+20, 4));
+ elf_arch_name(elf_get(&elf, 2)));
+ printf(" Version: 0x%llx\n", elf_int(&elf));
printf(" Entry point address: 0x%x\n", entry);
printf(" Start of program headers: %lld (bytes into file)\n",
TT.phoff);
@@ -374,15 +389,13 @@ static void scan_elf()
printf("There are %d section headers, starting at offset %#llx:\n",
TT.shnum, TT.shoff);
}
- printf("\n"
- "Section Headers:\n"
+ printf("\nSection Headers:\n"
" [Nr] %-20s %-14s %-*s %-6s %-6s ES Flg Lk Inf Al\n",
"Name", "Type", w, "Address", "Off", "Size");
}
}
- // We need to iterate through the section headers even if we're not
- // dumping them, to find specific sections.
- for (i=0; i<TT.shnum; i++) {
+ // Iterate through section headers to find specific sections.
+ for (i = 0; i<TT.shnum; i++) {
get_sh(i, &s);
if (s.type == 2 /*SHT_SYMTAB*/) symtab = s;
else if (s.type == 6 /*SHT_DYNAMIC*/) dynamic = s;
@@ -393,15 +406,16 @@ static void scan_elf()
}
if (FLAG(S)) {
- char sh_flags[12] = {}, *p = sh_flags;
+ char sh_flags[12], *p = sh_flags;
for (j=0; j<12; j++) if (s.flags&(1<<j)) *p++="WAXxMSILOTC"[j];
+ *p = 0;
printf(" [%2d] %-20s %-14s %0*lx %06lx %06lx %02lx %3s %2d %2d %2ld\n",
i, s.name, sh_type(s.type), w, s.addr, s.offset, s.size,
s.entsize, sh_flags, s.link, s.info, s.addralign);
}
}
- if (FLAG(S) && TT.shnum) {
+ if (FLAG(S) && i) {
printf("Key:\n"
" (W)rite, (A)lloc, e(X)ecute, (M)erge, (S)trings, (I)nfo\n"
" (L)ink order, (O)S, (G)roup, (T)LS, (C)ompressed, x=unknown\n");
@@ -412,30 +426,26 @@ static void scan_elf()
if (!phnum) printf("There are no program headers in this file.\n");
else {
if (!FLAG(h)) {
- printf("Elf file type is %s\n"
- "Entry point %#x\n"
- "There are %d program headers, starting at offset %lld\n"
- "\n",
+ printf("Elf file type is %s\nEntry point %#x\n"
+ "There are %d program headers, starting at offset %lld\n\n"
et_type(elf_type), entry, phnum, TT.phoff);
}
printf("Program Headers:\n"
" %-14s %-8s %-*s %-*s %-7s %-7s Flg Align\n", "Type",
"Offset", w, "VirtAddr", w, "PhysAddr", "FileSiz", "MemSiz");
- for (i=0; i<phnum; i++) {
+ for (i = 0; i<phnum; i++) {
get_ph(i, &ph);
printf(" %-14s 0x%06lx 0x%0*lx 0x%0*lx 0x%05lx 0x%05lx %c%c%c %#lx\n",
ph_type(ph.type), ph.offset, w, ph.vaddr, w, ph.paddr,
- ph.filesz, ph.memsz, ph.flags&4?'R':' ', ph.flags&2?'W':' ',
- ph.flags&1?'E':' ', ph.align);
+ ph.filesz, ph.memsz, (ph.flags&4)?'R':' ', (ph.flags&2)?'W':' ',
+ (ph.flags&1)?'E':' ', ph.align);
if (ph.type == 3 /*PH_INTERP*/) {
printf(" [Requesting program interpreter: %*s]\n",
(int) ph.filesz-1, TT.elf+ph.offset);
}
}
- printf("\n"
- " Section to Segment mapping:\n"
- " Segment Sections...\n");
+ printf("\n Section to Segment mapping:\n Segment Sections...\n");
for (i=0; i<phnum; i++) {
get_ph(i, &ph);
printf(" %02d ", i);
@@ -461,9 +471,8 @@ static void scan_elf()
dynamic.offset, dynamic.size/dynamic.entsize,
w+2, "Tag", "Type", "Name/Value");
for (; dyn < end; dyn += dynamic.entsize) {
- int es = 4*(TT.bits+1);
- long tag = TT.elf_int(dyn, es), val = TT.elf_int(dyn+es, es);
- char *type = dt_type(tag);
+ char *type = dt_type(tag), dd = dyn
+ long tag = elf_long(&dd), val = elf_long(&dd);
printf(" 0x%0*lx %-20s ", w, tag, *type=='0' ? type : type+1);
if (*type == 'd') printf("%ld\n", val);
@@ -479,27 +488,23 @@ static void scan_elf()
int mask;
if (*type == 'F') printf("Flags: ");
- for (j=0; names[j].s; j++) {
- if (val & (mask=(1<<names[j].bit))) {
+ for (j=0; names[j].s; j++)
+ if (val & (mask = (1<<names[j].bit)))
printf("%s%s", names[j].s, (val &= ~mask) ? " " : "");
- }
- }
- if (val) printf("0x%lx", val);
- xputc('\n');
+ printf("0x%lx\n"+5*!val, val);
} else if (*type == 'N' || *type == 'R' || *type == 'S') {
printf("%s: [%s]\n", *type=='N' ? "Shared library" :
(*type=='R' ? "Library runpath" : "Library soname"),
TT.elf+dynstr.offset+val);
} else if (*type == 'P') {
- type = dt_type(val);
- j = strlen(type);
+ j = strlen(type = dt_type(val));
if (*type != '0') type += 2, j -= 3;
printf("%*.*s\n", j, j, type);
} else printf("0x%lx\n", val);
}
}
- if (FLAG(dyn_syms)) show_symbols(&dynsym, &dynstr);
+ if (FLAG(dyn_syms)||FLAG(s)) show_symbols(&dynsym, &dynstr);
if (FLAG(s)) show_symbols(&symtab, &strtab);
if (FLAG(n)) {
@@ -567,25 +572,22 @@ static void scan_elf()
void readelf_main(void)
{
- char **arg;
- int all = FLAG_d|FLAG_h|FLAG_l|FLAG_n|FLAG_S|FLAG_s|FLAG_dyn_syms;
+ int i, fd, all = FLAG_d|FLAG_h|FLAG_l|FLAG_n|FLAG_S|FLAG_s;
if (FLAG(a)) toys.optflags |= all;
- if (FLAG(s)) toys.optflags |= FLAG_dyn_syms;
if (!(toys.optflags & (all|FLAG_p|FLAG_x))) help_exit("needs a flag");
- for (arg = toys.optargs; *arg; arg++) {
- int fd = open(TT.f = *arg, O_RDONLY);
- struct stat sb;
-
- if (fd == -1) perror_msg("%s", TT.f);
+ for (i = 0; TT.f = toys.optargs[i]; i++) {
+ if (-1 == (fd = open(TT.f, O_RDONLY))) perror_msg_raw(TT.f);
else {
- if (fstat(fd, &sb)) perror_msg("%s", TT.f);
+ struct stat sb;
+
+ if (fstat(fd, &sb)) perror_msg_raw(TT.f);
else if (!sb.st_size) error_msg("%s: empty", TT.f);
else if (!S_ISREG(sb.st_mode)) error_msg("%s: not a regular file",TT.f);
else {
TT.elf = xmmap(NULL, TT.size=sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
- scan_elf();
+ scan_elf(fd, sb.st_size);
munmap(TT.elf, TT.size);
}
close(fd);
_______________________________________________
Toybox mailing list
[email protected]
http://lists.landley.net/listinfo.cgi/toybox-landley.net