⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image.cc

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 CC
📖 第 1 页 / 共 2 页
字号:

        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 + -