Refactor BasicElf synth_elf unitest
A=Mike Hommey <mh@glandium.org> R=ted at https://breakpad.appspot.com/544002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1141 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
b41ad66e93
commit
3a8617eb8c
3 changed files with 183 additions and 7 deletions
|
@ -20,6 +20,7 @@ ELF::ELF(uint16_t machine,
|
|||
: Section(endianness),
|
||||
addr_size_(file_class == ELFCLASS64 ? 8 : 4),
|
||||
program_count_(0),
|
||||
program_header_table_(endianness),
|
||||
section_count_(0),
|
||||
section_header_table_(endianness),
|
||||
section_header_strings_(endianness) {
|
||||
|
@ -115,7 +116,8 @@ int ELF::AddSection(const string& name, const Section& section,
|
|||
// sh_entsize
|
||||
.Append(endianness(), addr_size_, entsize);
|
||||
|
||||
sections_.push_back(ElfSection(section, type, offset, offset_label));
|
||||
sections_.push_back(ElfSection(section, type, addr, offset, offset_label,
|
||||
size));
|
||||
return index;
|
||||
}
|
||||
|
||||
|
@ -133,6 +135,58 @@ void ELF::AppendSection(ElfSection §ion) {
|
|||
}
|
||||
}
|
||||
|
||||
void ELF::AddSegment(int start, int end, uint32_t type, uint32_t flags) {
|
||||
assert(start > 0);
|
||||
assert(size_t(start) < sections_.size());
|
||||
assert(end > 0);
|
||||
assert(size_t(end) < sections_.size());
|
||||
++program_count_;
|
||||
|
||||
// p_type
|
||||
program_header_table_.D32(type);
|
||||
|
||||
if (addr_size_ == 8) {
|
||||
// p_flags
|
||||
program_header_table_.D32(flags);
|
||||
}
|
||||
|
||||
size_t filesz = 0;
|
||||
size_t memsz = 0;
|
||||
bool prev_was_nobits = false;
|
||||
for (int i = start; i <= end; ++i) {
|
||||
size_t size = sections_[i].size_;
|
||||
if (sections_[i].type_ != SHT_NOBITS) {
|
||||
assert(!prev_was_nobits);
|
||||
// non SHT_NOBITS sections are 4-byte aligned (see AddSection)
|
||||
size = (size + 3) & ~3;
|
||||
filesz += size;
|
||||
} else {
|
||||
prev_was_nobits = true;
|
||||
}
|
||||
memsz += size;
|
||||
}
|
||||
|
||||
program_header_table_
|
||||
// p_offset
|
||||
.Append(endianness(), addr_size_, sections_[start].offset_label_)
|
||||
// p_vaddr
|
||||
.Append(endianness(), addr_size_, sections_[start].addr_)
|
||||
// p_paddr
|
||||
.Append(endianness(), addr_size_, sections_[start].addr_)
|
||||
// p_filesz
|
||||
.Append(endianness(), addr_size_, filesz)
|
||||
// p_memsz
|
||||
.Append(endianness(), addr_size_, memsz);
|
||||
|
||||
if (addr_size_ == 4) {
|
||||
// p_flags
|
||||
program_header_table_.D32(flags);
|
||||
}
|
||||
|
||||
// p_align
|
||||
program_header_table_.Append(endianness(), addr_size_, 0);
|
||||
}
|
||||
|
||||
void ELF::Finish() {
|
||||
// Add the section header string table at the end.
|
||||
section_header_string_index_ = section_count_;
|
||||
|
@ -140,14 +194,19 @@ void ELF::Finish() {
|
|||
AddSection(".shstrtab", section_header_strings_, SHT_STRTAB);
|
||||
//printf("section_count_: %ld, sections_.size(): %ld\n",
|
||||
// section_count_, sections_.size());
|
||||
if (program_count_) {
|
||||
Mark(&program_header_label_);
|
||||
Append(program_header_table_);
|
||||
} else {
|
||||
program_header_label_ = 0;
|
||||
}
|
||||
|
||||
for (vector<ElfSection>::iterator it = sections_.begin();
|
||||
it < sections_.end(); ++it) {
|
||||
AppendSection(*it);
|
||||
}
|
||||
section_count_label_ = section_count_;
|
||||
program_count_label_ = program_count_;
|
||||
// TODO: allow adding entries to program header table
|
||||
program_header_label_ = 0;
|
||||
|
||||
// Section header table starts here.
|
||||
Mark(§ion_header_label_);
|
||||
|
|
|
@ -104,6 +104,10 @@ class ELF : public Section {
|
|||
uint32_t type, uint32_t flags = 0, uint64_t addr = 0,
|
||||
uint32_t link = 0, uint64_t entsize = 0, uint64_t offset = 0);
|
||||
|
||||
// Add a segment containing from section index start to section index end.
|
||||
// The indexes must have been gotten from AddSection.
|
||||
void AddSegment(int start, int end, uint32_t type, uint32_t flags = 0);
|
||||
|
||||
// Write out all data. GetContents may be used after this.
|
||||
void Finish();
|
||||
|
||||
|
@ -116,6 +120,8 @@ class ELF : public Section {
|
|||
// Number of entries in the program header table.
|
||||
int program_count_;
|
||||
Label program_count_label_;
|
||||
// The program header table itself.
|
||||
Section program_header_table_;
|
||||
|
||||
// Offset to the section header table.
|
||||
Label section_header_label_;
|
||||
|
@ -133,15 +139,17 @@ class ELF : public Section {
|
|||
|
||||
// Record of an added section
|
||||
struct ElfSection : public Section {
|
||||
ElfSection(const Section& section, uint32_t type, uint32_t offset,
|
||||
Label offset_label)
|
||||
: Section(section), type_(type), offset_(offset)
|
||||
, offset_label_(offset_label) {
|
||||
ElfSection(const Section& section, uint32_t type, uint32_t addr,
|
||||
uint32_t offset, Label offset_label, uint32_t size)
|
||||
: Section(section), type_(type), addr_(addr), offset_(offset)
|
||||
, offset_label_(offset_label), size_(size) {
|
||||
}
|
||||
|
||||
uint32_t type_;
|
||||
uint32_t addr_;
|
||||
uint32_t offset_;
|
||||
Label offset_label_;
|
||||
uint32_t size_;
|
||||
};
|
||||
|
||||
vector<ElfSection> sections_;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
using google_breakpad::ElfClass32;
|
||||
using google_breakpad::ElfClass64;
|
||||
using google_breakpad::synth_elf::ELF;
|
||||
using google_breakpad::synth_elf::Section;
|
||||
using google_breakpad::synth_elf::StringTable;
|
||||
using google_breakpad::synth_elf::SymbolTable;
|
||||
using google_breakpad::test_assembler::Endianness;
|
||||
|
@ -260,4 +261,112 @@ TYPED_TEST(BasicElf, EmptyLE) {
|
|||
EXPECT_EQ(0U, shdr[1].sh_entsize);
|
||||
}
|
||||
|
||||
TYPED_TEST(BasicElf, BasicLE) {
|
||||
typedef typename TypeParam::Ehdr Ehdr;
|
||||
typedef typename TypeParam::Phdr Phdr;
|
||||
typedef typename TypeParam::Shdr Shdr;
|
||||
const size_t kStringTableSize = sizeof("\0.text\0.bss\0.shstrtab");
|
||||
const size_t kStringTableAlign = 4 - kStringTableSize % 4;
|
||||
const size_t kExpectedSize = sizeof(Ehdr) +
|
||||
// Four sections, SHT_NULL + the section header string table +
|
||||
// 4096 bytes of the size-aligned .text section + one program header.
|
||||
sizeof(Phdr) + 4 * sizeof(Shdr) + 4096 +
|
||||
kStringTableSize + kStringTableAlign;
|
||||
|
||||
// It doesn't really matter that the machine type is right for the class.
|
||||
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
|
||||
Section text(kLittleEndian);
|
||||
text.Append(4094, 0);
|
||||
int text_idx = elf.AddSection(".text", text, SHT_PROGBITS);
|
||||
Section bss(kLittleEndian);
|
||||
bss.Append(16, 0);
|
||||
int bss_idx = elf.AddSection(".bss", bss, SHT_NOBITS);
|
||||
elf.AddSegment(text_idx, bss_idx, PT_LOAD);
|
||||
elf.Finish();
|
||||
EXPECT_EQ(kExpectedSize, elf.Size());
|
||||
|
||||
string contents;
|
||||
ASSERT_TRUE(elf.GetContents(&contents));
|
||||
ASSERT_EQ(kExpectedSize, contents.size());
|
||||
const Ehdr* header =
|
||||
reinterpret_cast<const Ehdr*>(contents.data());
|
||||
const uint8_t kIdent[] = {
|
||||
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
|
||||
TypeParam::kClass, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent)));
|
||||
EXPECT_EQ(ET_EXEC, header->e_type);
|
||||
EXPECT_EQ(EM_386, header->e_machine);
|
||||
EXPECT_EQ(static_cast<unsigned int>(EV_CURRENT), header->e_version);
|
||||
EXPECT_EQ(0U, header->e_entry);
|
||||
EXPECT_EQ(sizeof(Ehdr), header->e_phoff);
|
||||
EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr) + 4096 + kStringTableSize +
|
||||
kStringTableAlign, header->e_shoff);
|
||||
EXPECT_EQ(0U, header->e_flags);
|
||||
EXPECT_EQ(sizeof(Ehdr), header->e_ehsize);
|
||||
EXPECT_EQ(sizeof(Phdr), header->e_phentsize);
|
||||
EXPECT_EQ(1, header->e_phnum);
|
||||
EXPECT_EQ(sizeof(Shdr), header->e_shentsize);
|
||||
EXPECT_EQ(4, header->e_shnum);
|
||||
EXPECT_EQ(3, header->e_shstrndx);
|
||||
|
||||
const Shdr* shdr =
|
||||
reinterpret_cast<const Shdr*>(contents.data() + header->e_shoff);
|
||||
EXPECT_EQ(0U, shdr[0].sh_name);
|
||||
EXPECT_EQ(static_cast<unsigned int>(SHT_NULL), shdr[0].sh_type);
|
||||
EXPECT_EQ(0U, shdr[0].sh_flags);
|
||||
EXPECT_EQ(0U, shdr[0].sh_addr);
|
||||
EXPECT_EQ(0U, shdr[0].sh_offset);
|
||||
EXPECT_EQ(0U, shdr[0].sh_size);
|
||||
EXPECT_EQ(0U, shdr[0].sh_link);
|
||||
EXPECT_EQ(0U, shdr[0].sh_info);
|
||||
EXPECT_EQ(0U, shdr[0].sh_addralign);
|
||||
EXPECT_EQ(0U, shdr[0].sh_entsize);
|
||||
|
||||
EXPECT_EQ(1U, shdr[1].sh_name);
|
||||
EXPECT_EQ(static_cast<unsigned int>(SHT_PROGBITS), shdr[1].sh_type);
|
||||
EXPECT_EQ(0U, shdr[1].sh_flags);
|
||||
EXPECT_EQ(0U, shdr[1].sh_addr);
|
||||
EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr), shdr[1].sh_offset);
|
||||
EXPECT_EQ(4094U, shdr[1].sh_size);
|
||||
EXPECT_EQ(0U, shdr[1].sh_link);
|
||||
EXPECT_EQ(0U, shdr[1].sh_info);
|
||||
EXPECT_EQ(0U, shdr[1].sh_addralign);
|
||||
EXPECT_EQ(0U, shdr[1].sh_entsize);
|
||||
|
||||
EXPECT_EQ(sizeof("\0.text"), shdr[2].sh_name);
|
||||
EXPECT_EQ(static_cast<unsigned int>(SHT_NOBITS), shdr[2].sh_type);
|
||||
EXPECT_EQ(0U, shdr[2].sh_flags);
|
||||
EXPECT_EQ(0U, shdr[2].sh_addr);
|
||||
EXPECT_EQ(0U, shdr[2].sh_offset);
|
||||
EXPECT_EQ(16U, shdr[2].sh_size);
|
||||
EXPECT_EQ(0U, shdr[2].sh_link);
|
||||
EXPECT_EQ(0U, shdr[2].sh_info);
|
||||
EXPECT_EQ(0U, shdr[2].sh_addralign);
|
||||
EXPECT_EQ(0U, shdr[2].sh_entsize);
|
||||
|
||||
EXPECT_EQ(sizeof("\0.text\0.bss"), shdr[3].sh_name);
|
||||
EXPECT_EQ(static_cast<unsigned int>(SHT_STRTAB), shdr[3].sh_type);
|
||||
EXPECT_EQ(0U, shdr[3].sh_flags);
|
||||
EXPECT_EQ(0U, shdr[3].sh_addr);
|
||||
EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr) + 4096, shdr[3].sh_offset);
|
||||
EXPECT_EQ(kStringTableSize, shdr[3].sh_size);
|
||||
EXPECT_EQ(0U, shdr[3].sh_link);
|
||||
EXPECT_EQ(0U, shdr[3].sh_info);
|
||||
EXPECT_EQ(0U, shdr[3].sh_addralign);
|
||||
EXPECT_EQ(0U, shdr[3].sh_entsize);
|
||||
|
||||
const Phdr* phdr =
|
||||
reinterpret_cast<const Phdr*>(contents.data() + header->e_phoff);
|
||||
EXPECT_EQ(static_cast<unsigned int>(PT_LOAD), phdr->p_type);
|
||||
EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr), phdr->p_offset);
|
||||
EXPECT_EQ(0U, phdr->p_vaddr);
|
||||
EXPECT_EQ(0U, phdr->p_paddr);
|
||||
EXPECT_EQ(4096U, phdr->p_filesz);
|
||||
EXPECT_EQ(4096U + 16U, phdr->p_memsz);
|
||||
EXPECT_EQ(0U, phdr->p_flags);
|
||||
EXPECT_EQ(0U, phdr->p_align);
|
||||
}
|
||||
|
||||
#endif // defined(__i386__) || defined(__x86_64__)
|
||||
|
|
Loading…
Reference in a new issue