📄 image.cc
字号:
newSections.push_back(s);
}
mSections = newSections;
}
void Image::buildSymbolStringTable(void)
{
sectionNames = new StringTable(*this);
mSections.push_back(sectionNames);
for (unsigned int i = 0; i < mSymtab->size(); i++) {
sectionNames->addString(mSymtab->get(i)->name());
}
}
void Image::buildSectionStringTable(void)
{
for (unsigned int i = 0; i < mSections.size(); i++) {
if (!mSections[i]) continue;
sectionNames->addString(mSections[i]->name());
}
}
void Image::buildStub(const char* section)
{
Section *libSection = NULL;
if (section)
{
vector<Section *> newSections;
for (unsigned int i = 0; i < mSections.size(); i++) {
Section *s = mSections[i];
if (!s) continue;
uint32_t type = s->type();
// elided: relocs, strtabs other than main strtab
if (!(type == SHT_NULL || type == SHT_SYMTAB))
continue;
newSections.push_back(s);
}
string name = string(".lib") + section;
libSection = new Section(*this, name, SHT_PROGBITS, 0, 0, NULL, 0);
mSymtab->addSymbol(libSection->baseSymbol());
newSections.push_back(libSection);
mSections = newSections;
}
mSymtab->sortSymbols();
if (libSection)
mSymtab->forceSection(libSection);
}
void Image::buildRelocations(void)
{
vector<Section *> newSections;
if (mGOT) mGOT->buildRelocations();
for (unsigned int i = 0; i < mSections.size(); i++) {
Section *s = mSections[i];
vector<Relocation>& rels = s->relocations();
if (rels.size() == 0) continue;
Elf32_Rela *relBytes = new Elf32_Rela[rels.size()];
for (unsigned int r = 0; r < rels.size(); r++) {
relBytes[r] = rels[r].asElf(*mSymtab);
}
string name = string(".rela") + s->name();
Section *relSection = new Section(*this, name, SHT_RELA, 0, 0, (uint8_t *)relBytes, rels.size() * sizeof(Elf32_Rela));
rels.erase(rels.begin(), rels.end());
relSection->setLink(find(mSections.begin(), mSections.end(), mSymtab) - mSections.begin());
relSection->setInfo(i);
relSection->setEntrySize(sizeof(Elf32_Rela));
newSections.push_back(relSection);
}
mSections.insert(mSections.end(), newSections.begin(), newSections.end());
}
// if id == -1:
// write 'name' file in .ro format with a resource for each section, starting with resource ID baseID
// else
// write 'name' file in .bin format, ignoring resType and baseID
void Image::write(const char *resType, int baseID, const char *name)
{
uint32_t bufLen = sizeof(Elf32_Ehdr) + mSections.size()*sizeof(Elf32_Shdr);
uint8_t *buf = (uint8_t *)calloc(bufLen, 1);
int lastID;
// fill out section data and section headers
bool toobig = false;
for (unsigned int i = 0; i < mSections.size(); i++) {
Elf32_Shdr *shdr = (Elf32_Shdr *)(buf + sizeof(Elf32_Ehdr));
Section *s = mSections[i];
uint32_t offset = bufLen;
s->emit(shdr+i, buf, bufLen);
if (s->type() == SHT_NOBITS) {
// .bss et al take no space in resources - no size check
inform("emitting section '%s' (type %d flags %d) at 0x%x (%d bytes)", s->name().c_str(), s->type(), s->flags(), offset, s->size());
} else {
if (s->thunkSize()) {
inform("emitting section '%s' (type %d flags %d) at 0x%x (%d bytes [%d for thunks])", s->name().c_str(), s->type(), s->flags(), offset, s->size(), s->thunkSize());
} else {
inform("emitting section '%s' (type %d flags %d) at 0x%x (%d bytes)", s->name().c_str(), s->type(), s->flags(), offset, s->size());
}
if (baseID != -1 && s->size() > RESOURCE_MAX) {
toobig = true;
}
}
if (s->isReadOnly() && s->alignment() > 4) {
error("Read-only section '%s' is more than 4-byte aligned %d",
s->name().c_str(), s->alignment());
}
}
if (toobig) {
warning("Some sections are over %d bytes. "
"Consider using ld's --split-by-file to reduce section size "
"and save dynamic heap memory at runtime.",
RESOURCE_MAX);
}
// fill out ELF header
Elf32_Ehdr *ehdr = (Elf32_Ehdr *)buf;
memcpy(ehdr, &mEhdr, sizeof(mEhdr));
ehdr->e_entry = 0;
ehdr->e_phoff = 0;
ehdr->e_shoff = sizeof(Elf32_Ehdr);
ehdr->e_phentsize = 0;
ehdr->e_phnum = 0;
ehdr->e_shentsize = sizeof(Elf32_Shdr);
ehdr->e_shnum = mSections.size();
ehdr->e_shstrndx = find(mSections.begin(), mSections.end(), sectionNames) - mSections.begin();
ehdr->e_type = ET_REL;
int fd = open(name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
if (fd < 0) { perror(name); exit(1); }
if (baseID == -1) {
// write everything together
swap_ehdr(ehdr);
::write(fd, buf, bufLen);
swap_ehdr(ehdr);
} else {
// count non-empty resources
// resource baseID+0 is ehdr+shdrs
// additional sections are in consecutive resources
// sections bigger than 64 KB are split into multiple resources
// section 0 (SHT_NULL) is skipped
int res_count = 0;
res_count++; // ehdr+shdrs
for (unsigned i = 1; i < ehdr->e_shnum; i++) {
Elf32_Shdr *shdr = i+(Elf32_Shdr *)(ehdr+1);
uint32_t type = swap32(shdr->sh_type);
size_t size = swap32(shdr->sh_size);
if (size == 0 || type == SHT_NULL || type == SHT_NOBITS) {
continue; // no resource
}
res_count += (size + RESOURCE_MAX - 1) / RESOURCE_MAX;
}
// gather .prc header (68K-swapped!)
// Most fields are blank because this is only enough of a .prc
// to work with build-prc.
prc_header prc;
memset(&prc, 0, sizeof(prc));
strcpy(prc.name, "foo");
prc.attr = swap16_68K(1); // dmHdrAttrResDB
prc.version = swap16_68K(1);
strncpy(prc.type, "RESO", 4);
strncpy(prc.creator, "pRES", 4);
prc.count = swap16_68K(res_count);
// gather resource headers
// resource baseID+0 is ehdr+shdrs
// additional sections are in consecutive resources
// sections bigger than 64 KB are split into multiple resources
// section 0 (SHT_NULL) is skipped
int r;
res_header res[res_count];
ptrdiff_t offset;
r = 0;
lastID = baseID;
offset = sizeof(prc) + sizeof(res) + 2;
strncpy(res[r].type, resType, 4);
res[r].id = swap16_68K(lastID);
res[r].offset = swap32_68K(offset);
r++;
lastID++;
offset += sizeof(*ehdr) + ehdr->e_shnum*ehdr->e_shentsize;
for (unsigned int i = 1; i < ehdr->e_shnum; i++) {
Elf32_Shdr *shdr = i+(Elf32_Shdr *)(ehdr+1);
uint32_t type = swap32(shdr->sh_type);
size_t size = swap32(shdr->sh_size);
if (size == 0 || type == SHT_NULL || type == SHT_NOBITS) {
continue; // no resource
}
while (1) {
strncpy(res[r].type, resType, 4);
res[r].id = swap16_68K(lastID);
res[r].offset = swap32_68K(offset);
r++;
lastID++;
if (size > RESOURCE_MAX) {
// section too big - do another resource
offset += RESOURCE_MAX;
size -= RESOURCE_MAX;
} else {
offset += size;
break;
}
}
}
// write prc header and resource headers
uint16_t gap = 0;
::write(fd, &prc, sizeof(prc));
::write(fd, res, sizeof(res));
::write(fd, &gap, 2);
// write resource data
swap_ehdr(ehdr);
::write(fd, buf, bufLen);
swap_ehdr(ehdr);
}
close(fd);
if (baseID == -1) {
inform("wrote file %s", name);
} else {
inform("wrote file %s (resource type '%s', id %d..%d)", name, resType, baseID, lastID-1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -