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:
ted.mielczarek@gmail.com 2013-04-04 16:24:38 +00:00
parent b41ad66e93
commit 3a8617eb8c
3 changed files with 183 additions and 7 deletions

View file

@ -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 &section) {
}
}
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(&section_header_label_);

View file

@ -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_;

View file

@ -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__)