summaryrefslogtreecommitdiff
path: root/compiler/linker
diff options
context:
space:
mode:
author David Srbecky <dsrbecky@google.com> 2018-07-05 22:27:08 +0100
committer David Srbecky <dsrbecky@google.com> 2018-07-17 17:17:00 +0100
commitde91fd4f92363c69bce2c21366fbb2a31c8c1e78 (patch)
treee7fd79f291caa7676c7d68ca537f1c62ce214f3e /compiler/linker
parent2449d6d006dcb685d3b386edcf624e67ef37e12c (diff)
Generate unstripped .oat files in the symbols directory.
Test: Check the generated files with readelf. Bug: 70512966 Change-Id: Id31232f8b750281bdc170f356833a8d71e1b5796
Diffstat (limited to 'compiler/linker')
-rw-r--r--compiler/linker/elf_builder.h52
1 files changed, 48 insertions, 4 deletions
diff --git a/compiler/linker/elf_builder.h b/compiler/linker/elf_builder.h
index 3da7a43762..974c590a65 100644
--- a/compiler/linker/elf_builder.h
+++ b/compiler/linker/elf_builder.h
@@ -308,9 +308,14 @@ class ElfBuilder FINAL {
/* link */ nullptr,
/* info */ 0,
align,
- /* entsize */ 0),
- current_offset_(0),
- last_offset_(0) {
+ /* entsize */ 0) {
+ Reset();
+ }
+
+ void Reset() {
+ current_offset_ = 0;
+ last_name_ = "";
+ last_offset_ = 0;
}
Elf_Word Write(const std::string& name) {
@@ -550,6 +555,7 @@ class ElfBuilder FINAL {
build_id_(this, ".note.gnu.build-id", SHT_NOTE, SHF_ALLOC, nullptr, 0, 4, 0),
current_section_(nullptr),
started_(false),
+ finished_(false),
write_program_headers_(false),
loaded_size_(0u),
virtual_address_(0) {
@@ -627,8 +633,10 @@ class ElfBuilder FINAL {
write_program_headers_ = write_program_headers;
}
- void End() {
+ off_t End() {
DCHECK(started_);
+ DCHECK(!finished_);
+ finished_ = true;
// Note: loaded_size_ == 0 for tests that don't write .rodata, .text, .bss,
// .dynstr, dynsym, .hash and .dynamic. These tests should not read loaded_size_.
@@ -662,6 +670,7 @@ class ElfBuilder FINAL {
Elf_Off section_headers_offset;
section_headers_offset = AlignFileOffset(sizeof(Elf_Off));
stream_.WriteFully(shdrs.data(), shdrs.size() * sizeof(shdrs[0]));
+ off_t file_size = stream_.Seek(0, kSeekCurrent);
// Flush everything else before writing the program headers. This should prevent
// the OS from reordering writes, so that we don't end up with valid headers
@@ -687,6 +696,39 @@ class ElfBuilder FINAL {
stream_.WriteFully(&elf_header, sizeof(elf_header));
stream_.WriteFully(phdrs.data(), phdrs.size() * sizeof(phdrs[0]));
stream_.Flush();
+
+ return file_size;
+ }
+
+ // This has the same effect as running the "strip" command line tool.
+ // It removes all debugging sections (but it keeps mini-debug-info).
+ // It returns the ELF file size (as the caller needs to truncate it).
+ off_t Strip() {
+ DCHECK(finished_);
+ finished_ = false;
+ Elf_Off end = 0;
+ std::vector<Section*> non_debug_sections;
+ for (Section* section : sections_) {
+ if (section == &shstrtab_ || // Section names will be recreated.
+ section == &symtab_ ||
+ section == &strtab_ ||
+ section->name_.find(".debug_") == 0) {
+ section->header_.sh_offset = 0;
+ section->header_.sh_size = 0;
+ section->section_index_ = 0;
+ } else {
+ if (section->header_.sh_type != SHT_NOBITS) {
+ DCHECK_LE(section->header_.sh_offset, end + kPageSize) << "Large gap between sections";
+ end = std::max<off_t>(end, section->header_.sh_offset + section->header_.sh_size);
+ }
+ non_debug_sections.push_back(section);
+ }
+ }
+ shstrtab_.Reset();
+ // Write the non-debug section headers, program headers, and ELF header again.
+ sections_ = std::move(non_debug_sections);
+ stream_.Seek(end, kSeekSet);
+ return End();
}
// The running program does not have access to section headers
@@ -861,6 +903,7 @@ class ElfBuilder FINAL {
void WriteBuildId(uint8_t build_id[kBuildIdLen]) {
stream_.Seek(build_id_.GetDigestStart(), kSeekSet);
stream_.WriteFully(build_id, kBuildIdLen);
+ stream_.Flush();
}
// Returns true if all writes and seeks on the output stream succeeded.
@@ -1060,6 +1103,7 @@ class ElfBuilder FINAL {
Section* current_section_; // The section which is currently being written.
bool started_;
+ bool finished_;
bool write_program_headers_;
// The size of the memory taken by the ELF file when loaded.