Rizin
unix-like reverse engineering framework and cli tools
elf_ehdr.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 08A <08A@riseup.net>
2 // SPDX-FileCopyrightText: 2021 RizinOrg <info@rizin.re>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include "elf.h"
6 
7 static Elf_(Half) get_tiny_elf_phnum(ELFOBJ *bin) {
8  ut64 offset = 44;
9 
10  ut8 tmp;
11  if (!Elf_(rz_bin_elf_read_char)(bin, &offset, &tmp)) {
12  RZ_LOG_WARN("Failed to read ELF header (e_phnum) in tiny elf mode.\n")
13  }
14 
15  return tmp;
16 }
17 
18 static bool is_tiny_elf(ELFOBJ *bin) {
19  return bin->size == 45;
20 }
21 
23  return Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_type) &&
24  Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_machine) &&
25  Elf_(rz_bin_elf_read_word)(bin, offset, &bin->ehdr.e_version) &&
26  Elf_(rz_bin_elf_read_addr)(bin, offset, &bin->ehdr.e_entry) &&
27  Elf_(rz_bin_elf_read_off)(bin, offset, &bin->ehdr.e_phoff) &&
28  Elf_(rz_bin_elf_read_off)(bin, offset, &bin->ehdr.e_shoff) &&
29  Elf_(rz_bin_elf_read_word)(bin, offset, &bin->ehdr.e_flags) &&
30  Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_ehsize) &&
31  Elf_(rz_bin_elf_read_half)(bin, offset, &bin->ehdr.e_phentsize);
32 }
33 
34 static bool read_ehdr_other(ELFOBJ *bin) {
36 
37  if (!read_ehdr_other_aux(bin, &offset)) {
38  RZ_LOG_WARN("Failed to read beginning of the ELF header (until e_phnum).\n")
39  return false;
40  }
41 
42  if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_phnum)) {
43  RZ_LOG_WARN("Failed to read ELF header (e_phnum).\n")
44  }
45 
46  if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_shentsize)) {
47  RZ_LOG_WARN("Failed to read ELF header (e_shentsize).\n")
48  }
49 
50  if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_shnum)) {
51  RZ_LOG_WARN("Failed to read ELF header (e_shnum).\n")
52  }
53 
54  if (!Elf_(rz_bin_elf_read_half)(bin, &offset, &bin->ehdr.e_shstrndx)) {
55  RZ_LOG_WARN("Failed to read ELF header (e_shstrndx).\n")
56  }
57 
58  if (is_tiny_elf(bin)) {
59  RZ_LOG_WARN("The binary seems to be a tiny elf (45 bytes). Reload e_phnum value.\n");
60  bin->ehdr.e_phnum = get_tiny_elf_phnum(bin);
61  }
62 
63  return true;
64 }
65 
66 static bool is_valid_elf_ident(ut8 *e_ident) {
67  return !memcmp(e_ident, ELFMAG, SELFMAG) || !memcmp(e_ident, CGCMAG, SCGCMAG);
68 }
69 
70 static bool print_ehdr_aux(ELFOBJ *bin, PrintfCallback cb, ut64 offset, const char *name, char *(*get_value)(ELFOBJ *bin)) {
71  char *tmp = get_value(bin);
72  if (!tmp) {
73  return false;
74  }
75 
76  cb("0x%08" PFMT64x " %-10s %s\n", offset, name, tmp);
77 
78  free(tmp);
79  return true;
80 }
81 
84 
85  return rz_str_newf("%d", bin->ehdr.e_ehsize);
86 }
87 
90 
91  return rz_str_newf("0x%08" PFMT64x, (ut64)bin->ehdr.e_entry);
92 }
93 
96 
97  return rz_str_newf("0x%04x", bin->ehdr.e_flags);
98 }
99 
102 
103  return rz_str_newf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
104  bin->ehdr.e_ident[0],
105  bin->ehdr.e_ident[1],
106  bin->ehdr.e_ident[2],
107  bin->ehdr.e_ident[3],
108  bin->ehdr.e_ident[4],
109  bin->ehdr.e_ident[5],
110  bin->ehdr.e_ident[6],
111  bin->ehdr.e_ident[7],
112  bin->ehdr.e_ident[8],
113  bin->ehdr.e_ident[9],
114  bin->ehdr.e_ident[10],
115  bin->ehdr.e_ident[11],
116  bin->ehdr.e_ident[12],
117  bin->ehdr.e_ident[13],
118  bin->ehdr.e_ident[14],
119  bin->ehdr.e_ident[15]);
120 }
121 
124 
125  return rz_str_newf("0x%04x", bin->ehdr.e_machine);
126 }
127 
130 
131  return rz_str_newf("%d", bin->ehdr.e_phentsize);
132 }
133 
136 
137  return rz_str_newf("%d", bin->ehdr.e_phnum);
138 }
139 
142 
143  return rz_str_newf("0x%08" PFMT64x, (ut64)bin->ehdr.e_phoff);
144 }
145 
148 
149  return rz_str_newf("%d", bin->ehdr.e_shentsize);
150 }
151 
154 
155  return rz_str_newf("%d", bin->ehdr.e_shnum);
156 }
157 
160 
161  return rz_str_newf("0x%08" PFMT64x, (ut64)bin->ehdr.e_shoff);
162 }
163 
166 
167  return rz_str_newf("%d", bin->ehdr.e_shstrndx);
168 }
169 
172 
173  return rz_str_newf("0x%04x", bin->ehdr.e_type);
174 }
175 
178 
179  return rz_str_newf("0x%08x", bin->ehdr.e_version);
180 }
181 
183  rz_return_val_if_fail(bin, false);
184 
185  memset(&bin->ehdr, 0, sizeof(Elf_(Ehdr)));
186 
187  if (rz_buf_read_at(bin->b, 0, bin->ehdr.e_ident, EI_NIDENT) < EI_NIDENT) {
188  RZ_LOG_WARN("Failed to read ELF header e_ident.\n")
189  return false;
190  }
191 
192  if (!is_valid_elf_ident(bin->ehdr.e_ident)) {
193  RZ_LOG_WARN("Invalid ELF identification.\n");
194  return false;
195  }
196 
197  bin->big_endian = bin->ehdr.e_ident[EI_DATA] == ELFDATA2MSB;
198 
199  return read_ehdr_other(bin);
200 }
201 
203  rz_return_val_if_fail(bin && cb, false);
204 
219 }
#define NULL
Definition: cris-opc.c:27
bool Elf_() rz_bin_elf_read_addr(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RZ_INOUT ut64 *offset, RZ_NONNULL RZ_OUT Elf_(Addr) *result)
Definition: elf_misc.c:82
#define ELFOBJ
Definition: elf.h:24
bool Elf_() rz_bin_elf_read_char(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RZ_INOUT ut64 *offset, RZ_NONNULL RZ_OUT ut8 *result)
Definition: elf_misc.c:52
bool Elf_() rz_bin_elf_read_off(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RZ_INOUT ut64 *offset, RZ_NONNULL RZ_OUT Elf_(Off) *result)
Definition: elf_misc.c:91
bool Elf_() rz_bin_elf_read_word(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RZ_INOUT ut64 *offset, RZ_NONNULL RZ_OUT Elf_(Word) *result)
Definition: elf_misc.c:62
bool Elf_() rz_bin_elf_read_half(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RZ_INOUT ut64 *offset, RZ_NONNULL RZ_OUT Elf_(Half) *result)
Definition: elf_misc.c:57
RZ_OWN char *Elf_() rz_bin_elf_get_e_type_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:170
RZ_OWN char *Elf_() rz_bin_elf_get_e_ehsize_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:82
bool Elf_() rz_bin_elf_get_ehdr(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:182
RZ_OWN char *Elf_() rz_bin_elf_get_e_phnum_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:134
RZ_OWN char *Elf_() rz_bin_elf_get_e_shstrndx_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:164
static bool read_ehdr_other_aux(ELFOBJ *bin, ut64 *offset)
Definition: elf_ehdr.c:22
static bool read_ehdr_other(ELFOBJ *bin)
Definition: elf_ehdr.c:34
RZ_OWN char *Elf_() rz_bin_elf_get_e_entry_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:88
RZ_OWN char *Elf_() rz_bin_elf_get_e_shoff_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:158
RZ_OWN char *Elf_() rz_bin_elf_get_e_shentsize_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:146
RZ_OWN char *Elf_() rz_bin_elf_get_e_machine_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:122
static Elf_(Half)
Definition: elf_ehdr.c:7
RZ_OWN char *Elf_() rz_bin_elf_get_e_flags_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:94
RZ_OWN char *Elf_() rz_bin_elf_get_e_version_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:176
RZ_OWN char *Elf_() rz_bin_elf_get_e_phoff_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:140
RZ_OWN char *Elf_() rz_bin_elf_get_e_indent_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:100
static bool is_tiny_elf(ELFOBJ *bin)
Definition: elf_ehdr.c:18
RZ_OWN char *Elf_() rz_bin_elf_get_e_shnum_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:152
static bool print_ehdr_aux(ELFOBJ *bin, PrintfCallback cb, ut64 offset, const char *name, char *(*get_value)(ELFOBJ *bin))
Definition: elf_ehdr.c:70
static bool is_valid_elf_ident(ut8 *e_ident)
Definition: elf_ehdr.c:66
bool Elf_() rz_bin_elf_print_ehdr(ELFOBJ *bin, RZ_NONNULL PrintfCallback cb)
Definition: elf_ehdr.c:202
RZ_OWN char *Elf_() rz_bin_elf_get_e_phentsize_as_string(RZ_NONNULL ELFOBJ *bin)
Definition: elf_ehdr.c:128
#define E_PHENTSIZE_OFFSET
Definition: elf_specs.h:54
#define E_MACHINE_OFFSET
Definition: elf_specs.h:47
#define CGCMAG
Definition: elf_specs.h:82
#define E_TYPE_OFFSET
Definition: elf_specs.h:46
#define E_SHNUM_OFFSET
Definition: elf_specs.h:57
#define E_VERSION_OFFSET
Definition: elf_specs.h:48
#define E_IDENT_OFFSET
Definition: elf_specs.h:45
#define E_FLAGS_OFFSET
Definition: elf_specs.h:52
#define E_SHENTSIZE_OFFSET
Definition: elf_specs.h:56
#define E_PHOFF_OFFSET
Definition: elf_specs.h:50
#define E_ENTRYPOINT_OFFSET
Definition: elf_specs.h:49
#define E_SHOFF_OFFSET
Definition: elf_specs.h:51
#define SCGCMAG
Definition: elf_specs.h:83
#define E_PHNUM_OFFSET
Definition: elf_specs.h:55
#define E_SHSTRNDX_OFFSET
Definition: elf_specs.h:58
#define E_EHSIZE_OFFSET
Definition: elf_specs.h:53
#define SELFMAG
Definition: glibc_elf.h:122
#define ELFMAG
Definition: glibc_elf.h:121
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
#define ELFDATA2MSB
Definition: common.h:59
#define EI_DATA
Definition: common.h:56
#define EI_NIDENT
Definition: internal.h:43
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NONNULL
Definition: rz_types.h:64
int(* PrintfCallback)(const char *str,...) RZ_PRINTF_CHECK(1
Definition: rz_types.h:233
#define PFMT64x
Definition: rz_types.h:393
Definition: malloc.c:26
Definition: z80asm.h:102
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const char * cb[]
Definition: z80_tab.h:176