mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-07-03 14:58:35 +00:00
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
|
@ -20,6 +20,7 @@ ELF::ELF(uint16_t machine,
|
||||||
: Section(endianness),
|
: Section(endianness),
|
||||||
addr_size_(file_class == ELFCLASS64 ? 8 : 4),
|
addr_size_(file_class == ELFCLASS64 ? 8 : 4),
|
||||||
program_count_(0),
|
program_count_(0),
|
||||||
|
program_header_table_(endianness),
|
||||||
section_count_(0),
|
section_count_(0),
|
||||||
section_header_table_(endianness),
|
section_header_table_(endianness),
|
||||||
section_header_strings_(endianness) {
|
section_header_strings_(endianness) {
|
||||||
|
@ -115,7 +116,8 @@ int ELF::AddSection(const string& name, const Section& section,
|
||||||
// sh_entsize
|
// sh_entsize
|
||||||
.Append(endianness(), addr_size_, 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;
|
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() {
|
void ELF::Finish() {
|
||||||
// Add the section header string table at the end.
|
// Add the section header string table at the end.
|
||||||
section_header_string_index_ = section_count_;
|
section_header_string_index_ = section_count_;
|
||||||
|
@ -140,14 +194,19 @@ void ELF::Finish() {
|
||||||
AddSection(".shstrtab", section_header_strings_, SHT_STRTAB);
|
AddSection(".shstrtab", section_header_strings_, SHT_STRTAB);
|
||||||
//printf("section_count_: %ld, sections_.size(): %ld\n",
|
//printf("section_count_: %ld, sections_.size(): %ld\n",
|
||||||
// section_count_, sections_.size());
|
// 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();
|
for (vector<ElfSection>::iterator it = sections_.begin();
|
||||||
it < sections_.end(); ++it) {
|
it < sections_.end(); ++it) {
|
||||||
AppendSection(*it);
|
AppendSection(*it);
|
||||||
}
|
}
|
||||||
section_count_label_ = section_count_;
|
section_count_label_ = section_count_;
|
||||||
program_count_label_ = program_count_;
|
program_count_label_ = program_count_;
|
||||||
// TODO: allow adding entries to program header table
|
|
||||||
program_header_label_ = 0;
|
|
||||||
|
|
||||||
// Section header table starts here.
|
// Section header table starts here.
|
||||||
Mark(§ion_header_label_);
|
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 type, uint32_t flags = 0, uint64_t addr = 0,
|
||||||
uint32_t link = 0, uint64_t entsize = 0, uint64_t offset = 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.
|
// Write out all data. GetContents may be used after this.
|
||||||
void Finish();
|
void Finish();
|
||||||
|
|
||||||
|
@ -116,6 +120,8 @@ class ELF : public Section {
|
||||||
// Number of entries in the program header table.
|
// Number of entries in the program header table.
|
||||||
int program_count_;
|
int program_count_;
|
||||||
Label program_count_label_;
|
Label program_count_label_;
|
||||||
|
// The program header table itself.
|
||||||
|
Section program_header_table_;
|
||||||
|
|
||||||
// Offset to the section header table.
|
// Offset to the section header table.
|
||||||
Label section_header_label_;
|
Label section_header_label_;
|
||||||
|
@ -133,15 +139,17 @@ class ELF : public Section {
|
||||||
|
|
||||||
// Record of an added section
|
// Record of an added section
|
||||||
struct ElfSection : public Section {
|
struct ElfSection : public Section {
|
||||||
ElfSection(const Section& section, uint32_t type, uint32_t offset,
|
ElfSection(const Section& section, uint32_t type, uint32_t addr,
|
||||||
Label offset_label)
|
uint32_t offset, Label offset_label, uint32_t size)
|
||||||
: Section(section), type_(type), offset_(offset)
|
: Section(section), type_(type), addr_(addr), offset_(offset)
|
||||||
, offset_label_(offset_label) {
|
, offset_label_(offset_label), size_(size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t type_;
|
uint32_t type_;
|
||||||
|
uint32_t addr_;
|
||||||
uint32_t offset_;
|
uint32_t offset_;
|
||||||
Label offset_label_;
|
Label offset_label_;
|
||||||
|
uint32_t size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
vector<ElfSection> sections_;
|
vector<ElfSection> sections_;
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
using google_breakpad::ElfClass32;
|
using google_breakpad::ElfClass32;
|
||||||
using google_breakpad::ElfClass64;
|
using google_breakpad::ElfClass64;
|
||||||
using google_breakpad::synth_elf::ELF;
|
using google_breakpad::synth_elf::ELF;
|
||||||
|
using google_breakpad::synth_elf::Section;
|
||||||
using google_breakpad::synth_elf::StringTable;
|
using google_breakpad::synth_elf::StringTable;
|
||||||
using google_breakpad::synth_elf::SymbolTable;
|
using google_breakpad::synth_elf::SymbolTable;
|
||||||
using google_breakpad::test_assembler::Endianness;
|
using google_breakpad::test_assembler::Endianness;
|
||||||
|
@ -260,4 +261,112 @@ TYPED_TEST(BasicElf, EmptyLE) {
|
||||||
EXPECT_EQ(0U, shdr[1].sh_entsize);
|
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__)
|
#endif // defined(__i386__) || defined(__x86_64__)
|
||||||
|
|
Loading…
Reference in a new issue