Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i#7046: Add padding to align loadable segments to page size in the core file. #7144

Merged
merged 7 commits into from
Dec 18, 2024
49 changes: 37 additions & 12 deletions core/unix/coredump.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
# error Unsupported architecture
#endif

#define MAX_BUFFER_SIZE 4096
#define MAX_SECTION_HEADERS 300
#define MAX_SECTION_NAME_BUFFER_SIZE 8192
#define SECTION_HEADER_TABLE ".shstrtab"
Expand Down Expand Up @@ -484,11 +485,23 @@ os_dump_core_internal(dcontext_t *dcontext)
// of LOAD program header (number of sections minus one since shstrtab does not
ivankyluk marked this conversation as resolved.
Show resolved Hide resolved
ivankyluk marked this conversation as resolved.
Show resolved Hide resolved
ivankyluk marked this conversation as resolved.
Show resolved Hide resolved
ivankyluk marked this conversation as resolved.
Show resolved Hide resolved
// require a LOAD header).
const ELF_OFF program_header_count = section_count;
// core_file_offset is the current offset of the core file to write the next
// section data.
ELF_OFF core_file_offset = sizeof(ELF_HEADER_TYPE) +
sizeof(ELF_PROGRAM_HEADER_TYPE) * program_header_count +
PROGRAM_HEADER_NOTE_LENGTH;
// We add padding to the core file so that loadable segments in the
// core file are page size aligned. The p_align field in the program header
// is applied to both memory and the offset to the core file.
const size_t loadable_segment_padding =
ALIGN_FORWARD(core_file_offset, os_page_size()) - core_file_offset;
core_file_offset = ALIGN_FORWARD(core_file_offset, os_page_size());

if (!write_elf_header(elf_file, /*entry_point=*/(uint64_t)mc.pc,
/*section_header_table_offset*/ sizeof(ELF_HEADER_TYPE) +
/*section_header_table_offset=*/sizeof(ELF_HEADER_TYPE) +
PROGRAM_HEADER_NOTE_LENGTH +
sizeof(ELF_PROGRAM_HEADER_TYPE) * program_header_count +
section_data_size,
loadable_segment_padding + section_data_size,
/*flags=*/0,
/*program_header_count=*/program_header_count,
/*section_header_count=*/section_count,
Expand All @@ -509,9 +522,6 @@ os_dump_core_internal(dcontext_t *dcontext)
return false;
}
// Write loadable program segment program headers.
ELF_OFF file_offset = sizeof(ELF_HEADER_TYPE) +
sizeof(ELF_PROGRAM_HEADER_TYPE) * program_header_count +
PROGRAM_HEADER_NOTE_LENGTH;
// TODO i#7046: Merge adjacent sections with the same prot values.
// The last section is shstrtab which stores the section names and it does
// not require a LOAD program header.
Expand All @@ -530,7 +540,7 @@ os_dump_core_internal(dcontext_t *dcontext)
section_header_info[section_index].vm_start;
if (!write_program_header(
elf_file, PT_LOAD, flags,
/*offset=*/file_offset,
/*offset=*/core_file_offset,
/*virtual_address=*/(ELF_ADDR)section_header_info[section_index].vm_start,
/*physical_address=*/
(ELF_ADDR)section_header_info[section_index].vm_start,
Expand All @@ -540,7 +550,7 @@ os_dump_core_internal(dcontext_t *dcontext)
os_close(elf_file);
return false;
}
file_offset += section_header_info[section_index].vm_end -
core_file_offset += section_header_info[section_index].vm_end -
section_header_info[section_index].vm_start;
}
if (!write_prstatus_note(&mc, elf_file)) {
Expand All @@ -551,6 +561,20 @@ os_dump_core_internal(dcontext_t *dcontext)
os_close(elf_file);
return false;
}
// Add padding to the core file such that loadable segments are aligned to
// the page size in the core file.
char buffer[MAX_BUFFER_SIZE];
size_t remaining_bytes = loadable_segment_padding;
memset(buffer, 0, MIN(MAX_BUFFER_SIZE, loadable_segment_padding));
while (remaining_bytes > 0) {
const size_t bytes = MIN(remaining_bytes, MAX_BUFFER_SIZE);
if (os_write(elf_file, buffer, bytes) != bytes) {
SYSLOG_INTERNAL_ERROR("Failed to add padding to the core dump file.");
os_close(elf_file);
return false;
}
remaining_bytes -= bytes;
}
// Write memory content to the core dump file.
for (int section_index = 0; section_index < section_count - 1; ++section_index) {
const size_t length = section_header_info[section_index].vm_end -
Expand All @@ -577,9 +601,9 @@ os_dump_core_internal(dcontext_t *dcontext)
return false;
}
// Write section headers to the core dump file.
file_offset = sizeof(ELF_HEADER_TYPE) +
core_file_offset = sizeof(ELF_HEADER_TYPE) +
sizeof(ELF_PROGRAM_HEADER_TYPE) * program_header_count +
PROGRAM_HEADER_NOTE_LENGTH;
PROGRAM_HEADER_NOTE_LENGTH + loadable_segment_padding;

// The section_count includes the section name section, so we need to skip
// it in the loop. The section name section is handled differently after
Expand All @@ -594,7 +618,8 @@ os_dump_core_internal(dcontext_t *dcontext)
}
if (!write_section_header(
elf_file, section_header_info[section_index].name_offset, SHT_PROGBITS,
flags, (ELF_ADDR)section_header_info[section_index].vm_start, file_offset,
flags, (ELF_ADDR)section_header_info[section_index].vm_start,
core_file_offset,
section_header_info[section_index].vm_end -
section_header_info[section_index].vm_start,
/*link=*/0,
Expand All @@ -603,13 +628,13 @@ os_dump_core_internal(dcontext_t *dcontext)
os_close(elf_file);
return false;
}
file_offset += section_header_info[section_index].vm_end -
core_file_offset += section_header_info[section_index].vm_end -
section_header_info[section_index].vm_start;
}
// Write the section name section.
if (!write_section_header(
elf_file, string_table_offset - strlen(SECTION_HEADER_TABLE), SHT_STRTAB,
/*flags=*/0, /*virtual_address=*/0, file_offset,
/*flags=*/0, /*virtual_address=*/0, core_file_offset,
/*section_size=*/string_table_offset, /*link=*/0,
/*info=*/0, /*alignment=*/1,
/*entry_size=*/0)) {
Expand Down
Loading