Rizin
unix-like reverse engineering framework and cli tools
elf_notes.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 08A <08A@riseup.net>
2 // SPDX-FileCopyrightText: 2008-2020 nibble <nibble.ds@gmail.com>
3 // SPDX-FileCopyrightText: 2008-2020 pancake <pancake@nopcode.org>
4 // SPDX-FileCopyrightText: 2008-2020 alvaro_fe <alvaro.felipe91@gmail.com>
5 // SPDX-License-Identifier: LGPL-3.0-only
6 
7 #include "elf.h"
8 
9 #define ROUND_UP_4(x) ((x) + (4 - 1)) / 4 * 4
10 
11 #define X86 0
12 #define X86_64 1
13 #define ARM 2
14 #define AARCH64 3
15 #define ARCH_LEN 4
16 
18  [X86] = { 160, 0x48, 32, 0x3c },
19  [X86_64] = { 216, 0x70, 64, 0x98 },
20  [ARM] = { 72, 0x48, 32, 0x34 },
21  [AARCH64] = { 272, 0x70, 64, 0xf8 }
22 };
23 
24 static bool parse_note_prstatus(ELFOBJ *bin, RzVector *notes, Elf_(Nhdr) * note_segment_header, ut64 offset) {
26  if (!layout) {
27  RZ_LOG_WARN("Fetching registers from core file not supported for this architecture.\n");
28  return false;
29  }
30 
31  RzBinElfNote *note = rz_vector_push(notes, NULL);
32  if (!note) {
33  return false;
34  }
35 
36  note->type = NT_PRSTATUS;
37 
38  note->prstatus.regstate_size = layout->regsize;
39  note->prstatus.regstate = RZ_NEWS(ut8, layout->regsize);
40  if (!note->prstatus.regstate) {
41  return false;
42  }
43 
44  if (rz_buf_read_at(bin->b, offset + layout->regdelta, note->prstatus.regstate, note->prstatus.regstate_size) != layout->regsize) {
45  RZ_LOG_WARN("Failed to read register state from CORE file\n");
46  return false;
47  }
48 
49  return true;
50 }
51 
53  return Elf_(rz_bin_elf_read_addr)(bin, offset, &file->start_vaddr) &&
54  Elf_(rz_bin_elf_read_addr)(bin, offset, &file->end_vaddr) &&
55  Elf_(rz_bin_elf_read_off)(bin, offset, &file->file_off);
56 }
57 
59  ut64 tmp = *offset;
60  if (!get_note_file_aux(bin, file, offset)) {
61  RZ_LOG_WARN("Failed to read NT_FILE at 0x%" PFMT64x ".\n", tmp);
62  }
63 
64  return true;
65 }
66 
68  if (!get_note_file(bin, file, offset)) {
69  return false;
70  }
71 
72  file->file = name;
73  return true;
74 }
75 
76 static bool parse_note_file(ELFOBJ *bin, RzVector *notes, Elf_(Nhdr) * note_segment_header, ut64 offset) {
77  Elf_(Addr) n_maps;
78  if (!Elf_(rz_bin_elf_read_addr)(bin, &offset, &n_maps)) {
79  return false;
80  }
81 
82  offset += sizeof(Elf_(Addr)); // skip page size always 1
83 
84  Elf_(Addr) strings_offset; // offset after the addr-array
85  if (!Elf_(rz_bin_elf_mul_addr)(&strings_offset, n_maps, sizeof(Elf_(Addr)) * 3)) {
86  return false;
87  }
88 
89  ut64 entry_offset = offset;
90  for (Elf_(Addr) i = 0; i < n_maps; i++) {
91  if (strings_offset >= note_segment_header->n_descsz) {
92  return false;
93  }
94 
95  char *name = rz_buf_get_nstring(bin->b, offset + strings_offset, note_segment_header->n_descsz);
96  if (!name) {
97  return false;
98  }
99 
100  RzBinElfNote *note = rz_vector_push(notes, NULL);
101  if (!note) {
102  free(name);
103  return false;
104  }
105 
106  note->type = NT_FILE;
107 
108  if (!set_note_file(bin, &note->file, &entry_offset, name)) {
109  return false;
110  }
111 
112  strings_offset += strlen(name) + 1;
113  }
114 
115  return true;
116 }
117 
118 static bool set_note(ELFOBJ *bin, RzVector *notes, Elf_(Nhdr) * note_segment_header, ut64 offset) {
119  switch (note_segment_header->n_type) {
120  case NT_FILE:
121  if (!parse_note_file(bin, notes, note_segment_header, offset)) {
122  RZ_LOG_WARN("Failed to parse NT_FILE.\n");
123  return false;
124  }
125  break;
126  case NT_PRSTATUS:
127  if (!parse_note_prstatus(bin, notes, note_segment_header, offset)) {
128  RZ_LOG_WARN("Failed to parse NT_PRSTATUS.\n");
129  return false;
130  }
131  break;
132  }
133 
134  return true;
135 }
136 
137 static bool read_note_segment_header(ELFOBJ *bin, ut64 *offset, Elf_(Nhdr) * note_segment_header) {
138  if (!Elf_(rz_bin_elf_read_word)(bin, offset, &note_segment_header->n_namesz)) {
139  return false;
140  }
141 
142  if (!Elf_(rz_bin_elf_read_word)(bin, offset, &note_segment_header->n_descsz)) {
143  return false;
144  }
145 
146  if (!Elf_(rz_bin_elf_read_word)(bin, offset, &note_segment_header->n_type)) {
147  return false;
148  }
149 
150  return true;
151 }
152 
153 static bool set_note_segment(ELFOBJ *bin, RzVector *notes, RzBinElfSegment *segment) {
154  ut64 offset = segment->data.p_offset;
155 
156  while (offset < segment->data.p_filesz) {
157  Elf_(Nhdr) note_segment_header;
158 
159  if (!read_note_segment_header(bin, &offset, &note_segment_header)) {
160  return false;
161  }
162 
163  offset += ROUND_UP_4(note_segment_header.n_namesz); // skip name
164 
165  if (!set_note(bin, notes, &note_segment_header, offset)) {
166  return false;
167  }
168 
169  offset += ROUND_UP_4(note_segment_header.n_descsz); // skip name
170  }
171 
172  return true;
173 }
174 
176  free(ptr->regstate);
177 }
178 
179 static void note_file_free(RzBinElfNoteFile *ptr) {
180  free(ptr->file);
181 }
182 
183 static void note_free(void *e, RZ_UNUSED void *user) {
184  RzBinElfNote *ptr = e;
185 
186  switch (ptr->type) {
187  case NT_FILE:
188  note_file_free(&ptr->file);
189  break;
190  case NT_PRSTATUS:
191  note_prstatus_free(&ptr->prstatus);
192  break;
193  }
194 }
195 
196 static void note_segment_free(void *e, RZ_UNUSED void *user) {
197  RzVector *ptr = e;
198  rz_vector_fini(ptr);
199 }
200 
203 
204  switch (bin->ehdr.e_machine) {
205  case EM_AARCH64:
206  return prstatus_layouts + AARCH64;
207  case EM_ARM:
208  return prstatus_layouts + ARM;
209  case EM_386:
210  return prstatus_layouts + X86;
211  case EM_X86_64:
212  return prstatus_layouts + X86_64;
213  }
214 
215  return NULL;
216 }
217 
219  rz_return_val_if_fail(bin, false);
220 
222  if (!result) {
223  return NULL;
224  }
225 
226  RzBinElfSegment *segment;
227  rz_bin_elf_foreach_segments(bin, segment) {
228  if (!segment->is_valid || segment->data.p_type != PT_NOTE) {
229  continue;
230  }
231 
232  RzVector *notes = rz_vector_push(result, NULL);
233  if (!notes) {
234  rz_vector_free(result);
235  return NULL;
236  }
237 
238  rz_vector_init(notes, sizeof(RzBinElfNote), note_free, NULL);
239 
240  if (!set_note_segment(bin, notes, segment)) {
241  rz_vector_fini(notes);
242  rz_vector_free(result);
243  return NULL;
244  }
245  }
246 
247  if (!rz_vector_len(result)) {
248  rz_vector_free(result);
249  return NULL;
250  }
251 
252  return result;
253 }
254 
256  rz_return_val_if_fail(bin, false);
257  return bin->notes;
258 }
#define e(frag)
lzma_index ** i
Definition: index.h:629
#define NULL
Definition: cris-opc.c:27
#define rz_bin_elf_foreach_segments(bin, segment)
Definition: elf.h:26
RzBinElfSegment
Definition: elf.h:131
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
RzBinElfNote
Definition: elf.h:182
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
RzBinElfNoteFile
Definition: elf.h:165
bool Elf_() rz_bin_elf_mul_addr(Elf_(Addr) *result, Elf_(Addr) addr, Elf_(Addr) value)
Definition: elf_misc.c:154
#define X86_64
Definition: elf_notes.c:12
static bool parse_note_prstatus(ELFOBJ *bin, RzVector *notes, Elf_(Nhdr) *note_segment_header, ut64 offset)
Definition: elf_notes.c:24
#define X86
Definition: elf_notes.c:11
#define ROUND_UP_4(x)
Definition: elf_notes.c:9
#define ARCH_LEN
Definition: elf_notes.c:15
static bool read_note_segment_header(ELFOBJ *bin, ut64 *offset, Elf_(Nhdr) *note_segment_header)
Definition: elf_notes.c:137
static void note_free(void *e, RZ_UNUSED void *user)
Definition: elf_notes.c:183
static void note_prstatus_free(RzBinElfNotePrStatus *ptr)
Definition: elf_notes.c:175
static bool set_note_segment(ELFOBJ *bin, RzVector *notes, RzBinElfSegment *segment)
Definition: elf_notes.c:153
static bool set_note_file(ELFOBJ *bin, RzBinElfNoteFile *file, ut64 *offset, char *name)
Definition: elf_notes.c:67
bool Elf_() rz_bin_elf_has_notes(RZ_NONNULL ELFOBJ *bin)
Definition: elf_notes.c:255
static RzBinElfPrStatusLayout prstatus_layouts[ARCH_LEN]
Definition: elf_notes.c:17
static bool parse_note_file(ELFOBJ *bin, RzVector *notes, Elf_(Nhdr) *note_segment_header, ut64 offset)
Definition: elf_notes.c:76
static bool get_note_file(ELFOBJ *bin, RzBinElfNoteFile *file, ut64 *offset)
Definition: elf_notes.c:58
static void note_segment_free(void *e, RZ_UNUSED void *user)
Definition: elf_notes.c:196
RZ_OWN RzVector *Elf_() rz_bin_elf_notes_new(RZ_NONNULL ELFOBJ *bin)
Definition: elf_notes.c:218
static void note_file_free(RzBinElfNoteFile *ptr)
Definition: elf_notes.c:179
#define ARM
Definition: elf_notes.c:13
#define AARCH64
Definition: elf_notes.c:14
RZ_BORROW RzBinElfPrStatusLayout *Elf_() rz_bin_elf_get_prstatus_layout(RZ_NONNULL ELFOBJ *bin)
Definition: elf_notes.c:201
static bool get_note_file_aux(ELFOBJ *bin, RzBinElfNoteFile *file, ut64 *offset)
Definition: elf_notes.c:52
static bool set_note(ELFOBJ *bin, RzVector *notes, Elf_(Nhdr) *note_segment_header, ut64 offset)
Definition: elf_notes.c:118
#define Elf_(name)
Definition: elf_specs.h:32
#define EM_AARCH64
Definition: elf_specs.h:161
#define NT_FILE
Definition: glibc_elf.h:752
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
#define EM_X86_64
Definition: common.h:151
#define PT_NOTE
Definition: common.h:306
#define EM_386
Definition: common.h:105
#define NT_PRSTATUS
Definition: common.h:393
#define EM_ARM
Definition: common.h:129
const char * name
Definition: op.c:541
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API RZ_OWN char * rz_buf_get_nstring(RZ_NONNULL RzBuffer *b, ut64 addr, size_t size)
Get a string with a max length from the buffer.
Definition: buf.c:585
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
#define RZ_NEWS(x, y)
Definition: rz_types.h:283
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_UNUSED
Definition: rz_types.h:73
#define RZ_NONNULL
Definition: rz_types.h:64
#define PFMT64x
Definition: rz_types.h:393
#define RZ_BORROW
Definition: rz_types.h:63
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
RZ_API void rz_vector_free(RzVector *vec)
Definition: vector.c:75
RZ_API RzVector * rz_vector_new(size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:42
static size_t rz_vector_len(const RzVector *vec)
Definition: rz_vector.h:82
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
Definition: malloc.c:26
Definition: gzappend.c:170
Definition: z80asm.h:102
Information about the binary layout in a NT_PRSTATUS note for core files of a certain architecture an...
Definition: elf.h:82
ut64 regsize
Definition: elf.h:83
ut64 regdelta
Definition: elf.h:94
Parsed PT_NOTE of type NT_PRSTATUS.
Definition: elf.h:168
ut64(WINAPI *w32_GetEnabledXStateFeatures)()