/programs/develop/clink/epep/epep.h |
---|
61,6 → 61,8 |
EPEP_ERR_INVALID_BASE_RELOCATION_BLOCK_BASE_RELOCATION_OFFSET, |
EPEP_ERR_INVALID_SECTION_RELOCATION_OFFSET, |
EPEP_ERR_INVALID_LINENUMBER_OFFSET, |
EPEP_ERR_INVALID_NUMBER_OF_RELOCATIONS_FOR_EXTENDED, |
EPEP_ERR_END |
} EpepError; |
// |
285,10 → 287,10 |
/// Returns non-zero if export table exists in the file |
int epep_has_export_table(Epep *epep); |
/// Palces offset of export table into epep structrue |
/// Palces offset of export table into epep structure |
int epep_read_export_table_offset(Epep *epep); |
/// Palces export table into epep structrue |
/// Palces export table into epep structure |
//! Needs to be called before next export functions |
int epep_read_export_directory(Epep *epep); |
360,8 → 362,23 |
uint16_t Type; |
} EpepCoffRelocation; |
/// Gives a COFF Relocation by its index |
int epep_get_section_relocation_by_index(Epep *epep, EpepSectionHeader *sh, EpepCoffRelocation *rel, size_t index); |
/// Checks if the section contains more than 2^16 - 1 relocations |
int epep_section_contains_extended_relocations(Epep *epep, EpepSectionHeader *sh, int *result); |
/// Gives the section relocation count if the section contains more than 2^16 - 1 relocations |
int epep_get_section_extended_number_of_relocations(Epep *epep, EpepSectionHeader *sh, size_t *result); |
/// Gives the meaningful COFF Relocation count |
//! Returns the value to pass to the following _x functions in the last parameter |
int epep_get_section_number_of_relocations_x(Epep *epep, EpepSectionHeader *sh, size_t *result, int *extended); |
/// Gives a meaningful COFF Relocation by its index |
//! Requires the value returned by epep_get_section_number_of_relocations_x as the last argument |
int epep_get_section_relocation_by_index_x(Epep *epep, EpepSectionHeader *sh, EpepCoffRelocation *rel, size_t index, int extended); |
// |
// COFF Line Numbers |
// |
1004,6 → 1021,49 |
return 1; |
} |
int epep_section_contains_extended_relocations(Epep *epep, EpepSectionHeader *sh, int *result) { |
const uint32_t flag_IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000; |
if (sh->Characteristics & flag_IMAGE_SCN_LNK_NRELOC_OVFL) { |
if (sh->NumberOfRelocations != 0xffff) { |
epep->error_code = EPEP_ERR_INVALID_NUMBER_OF_RELOCATIONS_FOR_EXTENDED; |
return 0; |
} |
*result = 1; |
} else { |
*result = 0; |
} |
return 1; |
} |
int epep_get_section_extended_number_of_relocations(Epep *epep, EpepSectionHeader *sh, size_t *result) { |
EpepCoffRelocation first_relocation; |
if (!epep_get_section_relocation_by_index(epep, sh, &first_relocation, 0)) { |
return 0; |
} |
*result = first_relocation.VirtualAddress; |
return 1; |
} |
int epep_get_section_number_of_relocations_x(Epep *epep, EpepSectionHeader *sh, size_t *result, int *extended) { |
if (!epep_section_contains_extended_relocations(epep, sh, extended)) { |
return 0; |
} |
if (*extended) { |
size_t real_number_of_relocations; |
if (!epep_get_section_extended_number_of_relocations(epep, sh, &real_number_of_relocations)) { |
return 0; |
} |
*result = real_number_of_relocations - 1; |
} else { |
*result = sh->NumberOfRelocations; |
} |
return 1; |
} |
int epep_get_section_relocation_by_index_x(Epep *epep, EpepSectionHeader *sh, EpepCoffRelocation *rel, size_t index, int extended) { |
return epep_get_section_relocation_by_index(epep, sh, rel, index + extended); |
} |
// |
// COFF Line Numbers |
// |
/programs/develop/clink/main.c |
---|
43,8 → 43,12 |
"EPEP_ERR_INVALID_BASE_RELOCATION_BLOCK_BASE_RELOCATION_OFFSET", |
"EPEP_ERR_INVALID_SECTION_RELOCATION_OFFSET", |
"EPEP_ERR_INVALID_LINENUMBER_OFFSET", |
"EPEP_ERR_INVALID_NUMBER_OF_RELOCATIONS_FOR_EXTENDED", |
}; |
static_assert(sizeof(epep_errors) / sizeof(epep_errors[0]) == EPEP_ERR_END, |
"Each EPEP error should be stringified."); |
typedef char *pchar; |
typedef struct { |
63,6 → 67,8 |
uint32_t characteristics; |
size_t size; |
size_t number_of_relocations; |
// Number of relocations is greater than 2^16 - 1 |
int number_of_relocations_is_extended; |
} SectionInfo; |
typedef struct { |
240,7 → 246,12 |
fwrite32(out, offset_to_next_relocation); // PointerToRelocations |
offset_to_next_relocation += si.number_of_relocations * 10; |
fwrite32(out, 0); // PointerToLinenumbers |
fwrite16(out, si.number_of_relocations); // NumberOfRelocations |
// NumberOfRelocations |
if (si.number_of_relocations_is_extended) { |
fwrite16(out, 0xffff); |
} else { |
fwrite16(out, si.number_of_relocations); |
} |
fwrite16(out, 0); // NumberOfLinenumbers |
fwrite32(out, si.characteristics); // Characteristics |
log_info("Done.\n"); |
294,6 → 305,11 |
SectionInfo si = cdict_CStr_SectionInfo_get_v(&ir->info_per_section, name); |
log_info(" Writing relocations of %s {\n", name); |
if (si.number_of_relocations_is_extended) { |
EpepCoffRelocation rel = { 0 }; |
rel.VirtualAddress = si.number_of_relocations; |
fwrite(&rel, 1, 10, out); |
} |
for (size_t i = 0; i < cvec_ObjIdSecId_size(&si.source); i++) { |
ObjIdSecId id = cvec_ObjIdSecId_at(&si.source, i); |
CoffObject *object = &ir->objects[id.obj_id]; |
313,10 → 329,15 |
if (!epep_get_section_header_by_index(epep, &sh, id.sec_id)) { |
ERROR_EPEP(epep); |
} |
for (size_t rel_i = 0; rel_i < sh.NumberOfRelocations; rel_i++) { |
size_t number_of_relocations = 0; |
int extended = 0; |
if (!epep_get_section_number_of_relocations_x(epep, &sh, &number_of_relocations, &extended)) { |
ERROR_EPEP(epep); |
} |
for (size_t rel_i = 0; rel_i < number_of_relocations; rel_i++) { |
EpepCoffRelocation rel = { 0 }; |
if (!epep_get_section_relocation_by_index(epep, &sh, &rel, rel_i)) { |
if (!epep_get_section_relocation_by_index_x(epep, &sh, &rel, rel_i, extended)) { |
ERROR_EPEP(epep); |
} |
log_info(" { %02x, %02x, %02x }", rel.VirtualAddress, rel.SymbolTableIndex, rel.Type); |
604,9 → 625,22 |
size_t sec_offset = si.size; |
cvec_size_t_push_back(&objects[i].section_offsets, sec_offset); |
size_t number_of_relocations = 0; |
int unused = 0; |
if (!epep_get_section_number_of_relocations_x(epep, &sh, &number_of_relocations, &unused)) { |
ERROR_EPEP(epep); |
} |
si.size += sh.SizeOfRawData; |
si.characteristics |= sh.Characteristics; |
si.number_of_relocations += sh.NumberOfRelocations; |
si.number_of_relocations += number_of_relocations; |
if (si.number_of_relocations > 0xffff && !si.number_of_relocations_is_extended) { |
// One more relocation to store the actual relocation number |
si.number_of_relocations++; |
si.number_of_relocations_is_extended = 1; |
const uint32_t flag_IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000; |
si.characteristics |= flag_IMAGE_SCN_LNK_NRELOC_OVFL; |
} |
cvec_ObjIdSecId_push_back(&si.source, (ObjIdSecId){ i, sec_i }); |
cdict_CStr_SectionInfo_add_vv(&info_per_section, strdup(name), si, CDICT_REPLACE_EXIST); |