Compare commits

...

4 Commits

Author SHA1 Message Date
Mario Hüttel faeab33375 Allow for ELF files without program headers e.g. unlinked object files. 2023-01-20 19:39:54 +01:00
Mario Hüttel 7e414f8576 Enhance verbose output of section table
* Add more section types to prevent "unknown" from printing
* Add alloc, exec, and write flags of sections to output table
2023-01-20 19:38:10 +01:00
Mario Hüttel 933680c80d Use builtin byteswap functions to perform endianess conversion 2023-01-20 19:37:10 +01:00
Mario Hüttel 891df1803e Add byteswap and endian destection code to elfpatch 2023-01-20 19:36:30 +01:00
1 changed files with 52 additions and 15 deletions

View File

@ -30,6 +30,19 @@
#include <fort.h>
#include <inttypes.h>
#include <patchelfcrc/crc-output-struct.h>
#include <byteswap.h>
static const union {
uint8_t data[4];
uint32_t val;
} _endianess_check_union = {{1u, 2u, 3u, 4u}};
enum endianess {
END_LITTLE = 0x04030201ul,
END_BIG = 0x01020304ul,
};
#define HOST_ENDIANESS (_endianess_check_union.value)
struct elf_section {
GElf_Shdr section_header;
@ -77,15 +90,16 @@ static uint32_t get_uint32_from_byte_string(const uint8_t *data, bool little_end
uint32_t out = 0ul;
int i;
/* Always shift in in big endian format */
for (i = 0; i < 4; i++) {
if (little_endian)
out >>= 8u;
else
out <<= 8u;
out |= (((uint32_t)data[i]) << (little_endian ? 24u : 0u));
out |= (uint32_t)data[i];
}
/* Swap bytes if little endian */
if (little_endian)
out = bswap_32(out);
return out;
}
@ -96,14 +110,12 @@ static void write_crc_to_byte_array(uint8_t *byte_array, uint32_t crc, uint8_t c
if (!byte_array)
return;
if (!little_endian)
crc = bswap_32(crc);
for (i = 0; i < crc_size_bytes; i++) {
if (little_endian) {
byte_array[i] = (uint8_t)(crc & 0xFFul);
crc >>= 8u;
} else {
byte_array[i] = (uint8_t)((crc & 0xFF000000ul) >> 24u);
crc <<= 8u;
}
byte_array[i] = (uint8_t)(crc & 0xFFul);
crc >>= 8u;
}
}
@ -136,6 +148,14 @@ static const char *section_type_to_str(Elf64_Word type)
return "INIT_ARRAY";
case SHT_FINI_ARRAY:
return "FINI_ARRAY";
case SHT_PREINIT_ARRAY:
return "PREINIT_ARRAY";
case SHT_DYNAMIC:
return "DYNAMIC";
case SHT_ARM_ATTRIBUTES:
return "ARM_ATTRIBUTES";
case SHT_ARM_PREEMPTMAP:
return "ARM_PREEMPTMAP";
default:
break;
}
@ -147,6 +167,7 @@ static void print_sections(elfpatch_handle_t *ep)
SlList *iter;
ft_table_t *table;
const struct elf_section *section;
bool alloc, write, exec;
ret_if_ep_err(ep);
@ -162,15 +183,23 @@ static void print_sections(elfpatch_handle_t *ep)
/* Write header */
ft_set_cell_prop(table, 0, FT_ANY_COLUMN, FT_CPROP_ROW_TYPE, FT_ROW_HEADER);
ft_write_ln(table, "Section", "Type", "Size", "VMA", "LMA", "File Offset");
ft_write_ln(table, "Section", "Type", "ALLOC", "WRITE", "EXEC", "Size", "VMA", "LMA", "File Offset");
for (iter = ep->sections; iter; iter = sl_list_next(iter)) {
section = (const struct elf_section *)iter->data;
if (!section)
continue;
ft_printf_ln(table, "%s|%s|%lu|%p|%p|%p",
alloc = !!(section->section_header.sh_flags & SHF_ALLOC);
write = !!(section->section_header.sh_flags & SHF_WRITE);
exec = !!(section->section_header.sh_flags & SHF_EXECINSTR);
ft_printf_ln(table, "%s|%s|%s|%s|%s|%lu|%p|%p|%p",
section->name,
section_type_to_str(section->section_header.sh_type),
alloc ? "x" : "",
write ? "x" : "",
exec ? "x" : "",
section->section_header.sh_size,
(void *)section->section_header.sh_addr,
(void *)section->lma,
@ -261,6 +290,12 @@ static int elf_patch_read_program_headers(elfpatch_handle_t *ep)
return -1;
}
if (header_count == 0) {
/* No program headers found. This ELF file is probably not linked */
ep->program_headers_count = 0;
return 0;
}
ep->program_headers = (GElf_Phdr *)malloc(header_count * sizeof(GElf_Phdr));
if (!ep->program_headers) {
/* Mem error. Abort. Program will crash eventually */
@ -306,9 +341,11 @@ static void resolve_section_lmas(elfpatch_handle_t *ep)
if (!sec)
continue;
/* By default each sections LMA is assumed to be its LMA as well */
sec->lma = (uint64_t)sec->section_header.sh_addr;
if (sec->section_header.sh_type == SHT_NOBITS) {
/* Section does not contain data. It may be allocated but is not loaded. Therefore, LMA=VMA. */
sec->lma = (uint64_t)sec->section_header.sh_addr;
continue;
}