readelf: return error in case of invalid file

GNU readelf exits with an error for a number of invalid file cases.
Previously ELF Tool Chain readelf always exited with 0.  Now we exit 1
upon detecting an error with one or more input files, but in any case
all of them are processed.

This should catch common failure cases.  We still do not report an error
for some types of malformed ELF files, but this is consistent with GNU
readelf.

PR:		252727
Reviewed by:	jkoshy, markj
MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D29377
This commit is contained in:
Ed Maste 2021-04-04 21:01:28 -04:00
parent 6f2addd838
commit ea444392bb

View File

@ -285,7 +285,7 @@ static const char *elf_osabi(unsigned int abi);
static const char *elf_type(unsigned int type);
static const char *elf_ver(unsigned int ver);
static const char *dt_type(unsigned int mach, unsigned int dtype);
static void dump_ar(struct readelf *re, int);
static bool dump_ar(struct readelf *re, int);
static void dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe);
static void dump_attributes(struct readelf *re);
static uint8_t *dump_compatibility_tag(uint8_t *p, uint8_t *pe);
@ -315,7 +315,7 @@ static void dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die,
Dwarf_Addr base);
static void dump_dwarf_str(struct readelf *re);
static void dump_eflags(struct readelf *re, uint64_t e_flags);
static void dump_elf(struct readelf *re);
static bool dump_elf(struct readelf *re);
static void dump_flags(struct flag_desc *fd, uint64_t flags);
static void dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab);
static void dump_dynamic(struct readelf *re);
@ -7211,18 +7211,18 @@ unload_sections(struct readelf *re)
}
}
static void
static bool
dump_elf(struct readelf *re)
{
/* Fetch ELF header. No need to continue if it fails. */
if (gelf_getehdr(re->elf, &re->ehdr) == NULL) {
warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
return;
return (false);
}
if ((re->ec = gelf_getclass(re->elf)) == ELFCLASSNONE) {
warnx("gelf_getclass failed: %s", elf_errmsg(-1));
return;
return (false);
}
if (re->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) {
re->dw_read = _read_msb;
@ -7266,6 +7266,7 @@ dump_elf(struct readelf *re)
dump_dwarf(re);
if (re->options & ~RE_H)
unload_sections(re);
return (true);
}
static void
@ -7311,7 +7312,7 @@ dump_dwarf(struct readelf *re)
dwarf_finish(re->dbg, &de);
}
static void
static bool
dump_ar(struct readelf *re, int fd)
{
Elf_Arsym *arsym;
@ -7362,14 +7363,14 @@ dump_ar(struct readelf *re, int fd)
}
if (elf_rand(re->ar, SARMAG) != SARMAG) {
warnx("elf_rand() failed: %s", elf_errmsg(-1));
return;
return (false);
}
}
process_members:
if ((re->options & ~RE_C) == 0)
return;
return (true);
cmd = ELF_C_READ;
while ((re->elf = elf_begin(fd, cmd, re->ar)) != NULL) {
@ -7389,11 +7390,14 @@ dump_ar(struct readelf *re, int fd)
elf_end(re->elf);
}
re->elf = re->ar;
return (true);
}
static void
static bool
dump_object(struct readelf *re, int fd)
{
bool rv = false;
if ((re->flags & DISPLAY_FILENAME) != 0)
printf("\nFile: %s\n", re->filename);
@ -7407,10 +7411,10 @@ dump_object(struct readelf *re, int fd)
warnx("Not an ELF file.");
goto done;
case ELF_K_ELF:
dump_elf(re);
rv = dump_elf(re);
break;
case ELF_K_AR:
dump_ar(re, fd);
rv = dump_ar(re, fd);
break;
default:
warnx("Internal: libelf returned unknown elf kind.");
@ -7418,6 +7422,7 @@ dump_object(struct readelf *re, int fd)
done:
elf_end(re->elf);
return (rv);
}
static void
@ -7765,7 +7770,7 @@ main(int argc, char **argv)
fileargs_t *fa;
struct readelf *re, re_storage;
unsigned long si;
int fd, opt, i;
int fd, opt, i, exit_code;
char *ep;
re = &re_storage;
@ -7906,16 +7911,19 @@ main(int argc, char **argv)
err(1, "Unable to enter capability mode");
}
exit_code = EXIT_SUCCESS;
for (i = 0; i < argc; i++) {
re->filename = argv[i];
fd = fileargs_open(fa, re->filename);
if (fd < 0) {
warn("open %s failed", re->filename);
exit_code = EXIT_FAILURE;
} else {
dump_object(re, fd);
if (!dump_object(re, fd))
exit_code = EXIT_FAILURE;
close(fd);
}
}
exit(EXIT_SUCCESS);
exit(exit_code);
}