Rizin
unix-like reverse engineering framework and cli tools
elf_segments.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 bool get_phdr_entry(ELFOBJ *bin, Elf_(Phdr) * segment, ut64 offset) {
8  if (!Elf_(rz_bin_elf_read_word)(bin, &offset, &segment->p_type) ||
9 #if RZ_BIN_ELF64
10  !Elf_(rz_bin_elf_read_word)(bin, &offset, &segment->p_flags) ||
11 #endif
12  !Elf_(rz_bin_elf_read_off)(bin, &offset, &segment->p_offset) ||
13  !Elf_(rz_bin_elf_read_addr)(bin, &offset, &segment->p_vaddr) ||
14  !Elf_(rz_bin_elf_read_addr)(bin, &offset, &segment->p_paddr) ||
15  !Elf_(rz_bin_elf_read_word_xword)(bin, &offset, &segment->p_filesz) ||
16  !Elf_(rz_bin_elf_read_word_xword)(bin, &offset, &segment->p_memsz) ||
17 #ifndef RZ_BIN_ELF64
18  !Elf_(rz_bin_elf_read_word)(bin, &offset, &segment->p_flags) ||
19 #endif
20  !Elf_(rz_bin_elf_read_word_xword)(bin, &offset, &segment->p_align)) {
21  return false;
22  }
23 
24  return true;
25 }
26 
28  if (!options->elf_checks_segments) {
29  return true;
30  }
31 
32  if (!entry->p_offset && !entry->p_vaddr && !entry->p_paddr && !entry->p_filesz && !entry->p_memsz) {
33  return true;
34  }
35 
36  Elf_(Off) end_off;
37  if (!Elf_(rz_bin_elf_add_off)(&end_off, entry->p_offset, entry->p_filesz) || end_off > bin->size) {
38  return false;
39  }
40 
41  if (!Elf_(rz_bin_elf_add_addr)(NULL, entry->p_vaddr, entry->p_memsz)) {
42  return false;
43  }
44 
45  if (entry->p_flags == PT_LOAD && (!entry->p_memsz || entry->p_filesz > entry->p_memsz)) {
46  return false;
47  }
48 
49  if (entry->p_align && entry->p_offset % entry->p_align != entry->p_vaddr % entry->p_align) {
50  return false;
51  }
52 
53  return true;
54 }
55 
57  if (!get_phdr_entry(bin, &segment->data, offset)) {
58  RZ_LOG_WARN("Failed to read segment entry at 0x%" PFMT64x ".\n", offset);
59  return false;
60  }
61 
62  segment->is_valid = verify_phdr_entry(bin, options, &segment->data);
63  if (!segment->is_valid) {
64  RZ_LOG_WARN("The segment %zu at 0x%" PFMT64x " seems to be invalid.\n", pos, offset);
65  }
66 
67  return true;
68 }
69 
71  RzVector *result = rz_vector_new(sizeof(RzBinElfSegment), NULL, NULL);
72  if (!result) {
73  return NULL;
74  }
75 
76  ut64 offset = bin->ehdr.e_phoff;
77 
78  for (size_t i = 0; i < count; i++) {
79  RzBinElfSegment *segment = rz_vector_push(result, NULL);
80  if (!segment) {
81  rz_vector_free(result);
82  return NULL;
83  }
84 
85  if (!get_elf_segment(bin, options, segment, offset, i)) {
86  rz_vector_free(result);
87  return NULL;
88  }
89 
90  offset += sizeof(Elf_(Phdr));
91  }
92 
93  if (!rz_vector_len(result)) {
94  rz_vector_free(result);
95  return NULL;
96  }
97 
98  return result;
99 }
100 
102  if (bin->ehdr.e_phnum != PN_XNUM) {
103  return bin->ehdr.e_phnum;
104  }
105 
106  if (!sections) {
107  RZ_LOG_WARN("Failed to fetch the number of segments because there are no sections.\n");
108  return 0;
109  }
110 
112  if (!section) {
113  RZ_LOG_WARN("Failed to fetch the number of segments from the section 0.\n");
114  return 0;
115  }
116 
117  return section->sh_info;
118 }
119 
122 
125  if (iter->data.p_type == type) {
126  return iter;
127  }
128  }
129 
130  return NULL;
131 }
132 
135 
137  if (!count) {
138  return NULL;
139  }
140 
141  if (!Elf_(rz_bin_elf_check_array)(bin, bin->ehdr.e_phoff, count, sizeof(Elf_(Phdr)))) {
142  RZ_LOG_WARN("Invalid program header (check array failed).\n");
143  return NULL;
144  }
145 
147 }
148 
150  rz_return_val_if_fail(bin, false);
151  return bin->segments;
152 }
lzma_index ** i
Definition: index.h:629
RzList * sections(RzBinFile *bf)
Definition: bin_ne.c:110
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
#define RZ_BIN_ELF64
Definition: elf64.c:5
#define rz_bin_elf_foreach_segments(bin, segment)
Definition: elf.h:26
bool Elf_() rz_bin_elf_read_word_xword(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RZ_INOUT ut64 *offset, RZ_NONNULL RZ_OUT Elf_(Word) *result)
Definition: elf_misc.c:117
bool Elf_() rz_bin_elf_add_off(Elf_(Off) *result, Elf_(Off) addr, Elf_(Off) value)
Definition: elf_misc.c:146
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
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_add_addr(Elf_(Addr) *result, Elf_(Addr) addr, Elf_(Addr) value)
Definition: elf_misc.c:138
bool Elf_() rz_bin_elf_check_array(RZ_NONNULL ELFOBJ *bin, Elf_(Off) offset, Elf_(Off) length, Elf_(Off) entry_size)
Definition: elf_misc.c:32
static size_t get_number_of_segments(ELFOBJ *bin, RzVector *sections)
Definition: elf_segments.c:101
static bool verify_phdr_entry(ELFOBJ *bin, RzBinObjectLoadOptions *options, Elf_(Phdr) *entry)
Definition: elf_segments.c:27
RZ_OWN RzVector *Elf_() rz_bin_elf_segments_new(RZ_NONNULL ELFOBJ *bin, RzVector *sections, RZ_NONNULL RzBinObjectLoadOptions *options)
Definition: elf_segments.c:133
static RzVector * get_segments_from_phdr(ELFOBJ *bin, size_t count, RzBinObjectLoadOptions *options)
Definition: elf_segments.c:70
bool Elf_() rz_bin_elf_has_segments(RZ_NONNULL ELFOBJ *bin)
Definition: elf_segments.c:149
static bool get_phdr_entry(ELFOBJ *bin, Elf_(Phdr) *segment, ut64 offset)
Definition: elf_segments.c:7
static bool get_elf_segment(ELFOBJ *bin, RzBinObjectLoadOptions *options, RzBinElfSegment *segment, ut64 offset, size_t pos)
Definition: elf_segments.c:56
RZ_BORROW RzBinElfSegment *Elf_() rz_bin_elf_get_segment_with_type(RZ_NONNULL ELFOBJ *bin, Elf_(Word) type)
Definition: elf_segments.c:120
#define Elf_(name)
Definition: elf_specs.h:32
#define PN_XNUM
Definition: glibc_elf.h:698
voidpf uLong offset
Definition: ioapi.h:144
#define PT_LOAD
Definition: common.h:303
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
int type
Definition: mipsasm.c:17
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NONNULL
Definition: rz_types.h:64
#define PFMT64x
Definition: rz_types.h:393
#define RZ_BORROW
Definition: rz_types.h:63
static void * rz_vector_index_ptr(RzVector *vec, size_t index)
Definition: rz_vector.h:88
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
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
Definition: malloc.c:26
Definition: zipcmp.c:77
int pos
Definition: main.c:11
ut64(WINAPI *w32_GetEnabledXStateFeatures)()