23
23
24
24
#include " Object.tcc"
25
25
26
+ #include < cassert>
27
+
26
28
namespace LIEF {
27
29
namespace ELF {
28
30
@@ -117,6 +119,13 @@ void Builder::build(void) {
117
119
}
118
120
}
119
121
122
+ if (this ->binary_ ->object_relocations ().size () > 0 ) {
123
+ try {
124
+ this ->build_section_relocations <ELF_T>();
125
+ } catch (const LIEF::exception& e) {
126
+ LOG (ERROR) << e.what ();
127
+ }
128
+ }
120
129
121
130
// Build sections
122
131
if (this ->binary_ ->sections_ .size () > 0 ) {
@@ -223,7 +232,8 @@ void Builder::build_sections(void) {
223
232
using Elf_Shdr = typename ELF_T::Elf_Shdr;
224
233
VLOG (VDEBUG) << " [+] Build sections" ;
225
234
226
- const Header& header = this ->binary_ ->header ();
235
+ // FIXME: Keep it global const and local non const
236
+ Header& header = this ->binary_ ->header ();
227
237
const Elf_Off section_headers_offset = header.section_headers_offset ();
228
238
229
239
std::vector<std::string> stringTableOpti =
@@ -238,27 +248,55 @@ void Builder::build_sections(void) {
238
248
}
239
249
240
250
Section* string_names_section = this ->binary_ ->sections_ [header.section_name_table_idx ()];
241
- string_names_section->content (section_names);
242
251
243
- // **Should** be safe since .shstr is located at the end of the binary
244
- // if (string_names_section->size() < section_names.size()) {
245
- // string_names_section = &(this->binary_->extend_section(*string_names_section, section_names.size() - string_names_section->size() + 1));
246
- // }
252
+ auto && it_symtab_section = std::find_if (
253
+ std::begin (this ->binary_ ->sections_ ),
254
+ std::end (this ->binary_ ->sections_ ),
255
+ [] (const Section* section)
256
+ {
257
+ return section != nullptr and section->type () == ELF_SECTION_TYPES::SHT_SYMTAB;
258
+ });
247
259
248
- for (size_t i = 0 ; i < this ->binary_ ->sections_ .size (); i++) {
249
- const Section* section = this ->binary_ ->sections_ [i];
250
- VLOG (VDEBUG) << " Writing back '" << section->name () << " '" ;
260
+ // If there is already a symtab section with a str_section that is the same
261
+ // as the str_section of sections, create a new one for str_section of sections
262
+ if (it_symtab_section != std::end (this ->binary_ ->sections_ )) {
263
+ Section& symbol_section = **it_symtab_section;
264
+ Section* symbol_str_section = nullptr ;
265
+ if (symbol_section.link () != 0 or
266
+ symbol_section.link () < this ->binary_ ->sections_ .size ()) {
267
+ symbol_str_section = this ->binary_ ->sections_ [symbol_section.link ()];
268
+ }
251
269
252
- auto && it_offset_name = std::search (
253
- std::begin (section_names),
254
- std::end (section_names),
255
- section->name ().c_str (),
256
- section->name ().c_str () + section->name ().size () + 1 );
270
+ if (symbol_str_section == string_names_section)
271
+ {
272
+ Section sec_str_section (" .shstrtab" , ELF_SECTION_TYPES::SHT_STRTAB);
273
+ sec_str_section.content (section_names);
257
274
258
- if (it_offset_name == std::end (section_names)) {
259
- throw LIEF::not_found (" " ); // TODO: msg
275
+ auto & new_str_section = this ->binary_ ->add (sec_str_section, false );
276
+
277
+ auto it = std::find_if (std::begin (this ->binary_ ->sections_ ),
278
+ std::end (this ->binary_ ->sections_ ),
279
+ [&new_str_section](Section* S) {
280
+ return S == &new_str_section;
281
+ });
282
+ assert (it != std::end (this ->binary_ ->sections_ ));
283
+
284
+ // FIXME: We should remove the old section
285
+ header.section_name_table_idx (std::distance (std::begin (this ->binary_ ->sections_ ), it));
286
+
287
+ return this ->build <ELF_T>();
260
288
}
289
+ }
261
290
291
+ // FIXME: Handle if we add sections names and we shoudl increase section size
292
+ string_names_section->content (section_names);
293
+
294
+ // First write every section and then the header because if we do all of it
295
+ // in a row, we will write the old header section after some new header so they
296
+ // will be remove
297
+ for (size_t i = 0 ; i < this ->binary_ ->sections_ .size (); i++) {
298
+ const Section* section = this ->binary_ ->sections_ [i];
299
+ VLOG (VDEBUG) << " Writing back '" << section->name () << " '" ;
262
300
263
301
// Write Section's content
264
302
if (section->size () > 0 ) {
@@ -278,7 +316,7 @@ void Builder::build_sections(void) {
278
316
section->name ().c_str () + section->name ().size () + 1 );
279
317
280
318
if (it_offset_name == std::end (section_names)) {
281
- throw LIEF::not_found (" " ); // TODO: msg
319
+ throw LIEF::not_found (" Section name not found " ); // TODO: msg
282
320
}
283
321
284
322
const Elf_Off offset_name = static_cast <Elf_Off>(std::distance (std::begin (section_names), it_offset_name));
@@ -438,6 +476,7 @@ void Builder::build_static_symbols(void) {
438
476
content.write_conv <Elf_Sym>(sym_hdr);
439
477
}
440
478
479
+ // FIXME: Handle increase of size in symbol_str_section
441
480
symbol_str_section.content (std::move (string_table));
442
481
symbol_section.content (std::move (content.raw ()));
443
482
@@ -1098,6 +1137,131 @@ void Builder::build_dynamic_symbols(void) {
1098
1137
1099
1138
}
1100
1139
1140
+ template <typename ELF_T>
1141
+ void Builder::build_section_relocations (void ) {
1142
+ using Elf_Addr = typename ELF_T::Elf_Addr;
1143
+ using Elf_Xword = typename ELF_T::Elf_Xword;
1144
+ using Elf_Sxword = typename ELF_T::Elf_Sxword;
1145
+
1146
+ using Elf_Rela = typename ELF_T::Elf_Rela;
1147
+ using Elf_Rel = typename ELF_T::Elf_Rel;
1148
+ VLOG (VDEBUG) << " [+] Building object relocations" ;
1149
+
1150
+ it_object_relocations object_relocations = this ->binary_ ->object_relocations ();
1151
+
1152
+ bool isRela = object_relocations[0 ].is_rela ();
1153
+ if (not std::all_of (
1154
+ std::begin (object_relocations),
1155
+ std::end (object_relocations),
1156
+ [isRela] (const Relocation& relocation) {
1157
+ return relocation.is_rela () == isRela;
1158
+ })) {
1159
+ throw LIEF::type_error (" Object relocations are not of the same type" );
1160
+ }
1161
+
1162
+ it_sections sections = this ->binary_ ->sections ();
1163
+
1164
+ std::vector<Section*> rel_section;
1165
+ for (Section& S: sections)
1166
+ if (S.type () == ((isRela)?ELF_SECTION_TYPES::SHT_RELA:ELF_SECTION_TYPES::SHT_REL))
1167
+ rel_section.push_back (&S);
1168
+
1169
+
1170
+ // FIXME: Warn if not rel section found?
1171
+
1172
+ for (Section* section: rel_section) {
1173
+
1174
+ if (section->information () == 0 or section->information () >= sections.size ())
1175
+ throw LIEF::not_found (" Unable to find associated section for SHT_REL{A} section" );
1176
+
1177
+ const size_t sh_info = section->information ();
1178
+
1179
+ Section& AssociatedSection = sections[sh_info];
1180
+
1181
+ std::vector<uint8_t > content;
1182
+ for (const Relocation& relocation : this ->binary_ ->object_relocations ()) {
1183
+
1184
+ // Only write relocation in the matching section
1185
+ // (relocation for .text in .rela.text)
1186
+ // FIXME: static relocation on a new section will be ignored (SILENTLY!!)
1187
+ if (relocation.section_ != &AssociatedSection)
1188
+ continue ;
1189
+
1190
+ uint32_t idx = 0 ;
1191
+ if (relocation.has_symbol ()) {
1192
+ const Symbol& symbol = relocation.symbol ();
1193
+ auto it_name = std::find_if (
1194
+ std::begin (this ->binary_ ->dynamic_symbols_ ),
1195
+ std::end (this ->binary_ ->dynamic_symbols_ ),
1196
+ [&symbol] (const Symbol* s) {
1197
+ return s == &symbol;
1198
+ });
1199
+
1200
+ if (it_name == std::end (this ->binary_ ->dynamic_symbols_ )) {
1201
+ // FIXME: Do we have a way to walk both?
1202
+ auto it_name = std::find_if (
1203
+ std::begin (this ->binary_ ->static_symbols_ ),
1204
+ std::end (this ->binary_ ->static_symbols_ ),
1205
+ [&symbol] (const Symbol* s) {
1206
+ return s == &symbol;
1207
+ });
1208
+
1209
+ if (it_name == std::end (this ->binary_ ->static_symbols_ )) {
1210
+ throw not_found (" Unable to find the symbol associated with the relocation" );
1211
+ }
1212
+ idx = static_cast <uint32_t >(std::distance (std::begin (this ->binary_ ->static_symbols_ ), it_name));
1213
+ } else
1214
+ idx = static_cast <uint32_t >(std::distance (std::begin (this ->binary_ ->dynamic_symbols_ ), it_name));
1215
+ }
1216
+
1217
+
1218
+ Elf_Xword info = 0 ;
1219
+ if (std::is_same<ELF_T, ELF32>::value) {
1220
+ info = (static_cast <Elf_Xword>(idx) << 8 ) | relocation.type ();
1221
+ } else {
1222
+ info = (static_cast <Elf_Xword>(idx) << 32 ) | (relocation.type () & 0xffffffffL );
1223
+ }
1224
+
1225
+ if (isRela) {
1226
+ Elf_Rela relahdr;
1227
+ relahdr.r_offset = static_cast <Elf_Addr>(relocation.address ());
1228
+ relahdr.r_info = static_cast <Elf_Xword>(info);
1229
+ relahdr.r_addend = static_cast <Elf_Sxword>(relocation.addend ());
1230
+
1231
+ content.insert (
1232
+ std::end (content),
1233
+ reinterpret_cast <uint8_t *>(&relahdr),
1234
+ reinterpret_cast <uint8_t *>(&relahdr) + sizeof (Elf_Rela));
1235
+
1236
+ } else {
1237
+ Elf_Rel relhdr;
1238
+ relhdr.r_offset = static_cast <Elf_Addr>(relocation.address ());
1239
+ relhdr.r_info = static_cast <Elf_Xword>(info);
1240
+
1241
+ content.insert (
1242
+ std::end (content),
1243
+ reinterpret_cast <uint8_t *>(&relhdr),
1244
+ reinterpret_cast <uint8_t *>(&relhdr) + sizeof (Elf_Rel));
1245
+ }
1246
+
1247
+ }
1248
+
1249
+ VLOG (VDEBUG) << " Section associated with object relocations: " << section->name ();
1250
+ VLOG (VDEBUG) << " Is Rela: " << std::boolalpha << isRela;
1251
+ // Relocation the '.rela.xxxx' section
1252
+ if (content.size () > section->original_size ()) {
1253
+ Section rela_section (section->name (), (isRela)?ELF_SECTION_TYPES::SHT_RELA:ELF_SECTION_TYPES::SHT_REL);
1254
+ rela_section.content (content);
1255
+ this ->binary_ ->add (rela_section, false );
1256
+ this ->binary_ ->remove (*section, true );
1257
+
1258
+ return this ->build <ELF_T>();
1259
+
1260
+ }
1261
+ section->content (std::move (content));
1262
+ }
1263
+ }
1264
+
1101
1265
template <typename ELF_T>
1102
1266
void Builder::build_dynamic_relocations (void ) {
1103
1267
using Elf_Addr = typename ELF_T::Elf_Addr;
0 commit comments