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

📄 linker.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* linker.cpp --   This file is part of the UPX executable compressor.   Copyright (C) 1996-2007 Markus Franz Xaver Johannes Oberhumer   Copyright (C) 1996-2007 Laszlo Molnar   All Rights Reserved.   UPX and the UCL library are free software; you can redistribute them   and/or modify them under the terms of the GNU General Public License as   published by the Free Software Foundation; either version 2 of   the License, or (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; see the file COPYING.   If not, write to the Free Software Foundation, Inc.,   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.   Markus F.X.J. Oberhumer   Laszlo Molnar   markus@oberhumer.com      ml1050@users.sourceforge.net */#include "conf.h"#include "linker.h"static unsigned hex(unsigned char c){    return (c & 0xf) + (c > '9' ? 9 : 0);}static bool update_capacity(unsigned size, unsigned *capacity){    if (size < *capacity)        return false;    if (*capacity == 0)        *capacity = 16;    while (size >= *capacity)        *capacity *= 2;    return true;}/*************************************************************************// Section**************************************************************************/ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a) :    name(NULL), output(NULL), size(s), offset(0), p2align(a), next(NULL){    name = strdup(n);    assert(name != NULL);    input = malloc(s + 1);    assert(input != NULL);    memcpy(input, i, s);    ((char *)input)[s] = 0;}ElfLinker::Section::~Section(){    free(name);    free(input);}/*************************************************************************// Symbol**************************************************************************/ElfLinker::Symbol::Symbol(const char *n, Section *s, unsigned o) :    name(NULL), section(s), offset(o){    name = strdup(n);    assert(name != NULL);    assert(section != NULL);}ElfLinker::Symbol::~Symbol(){    free(name);}/*************************************************************************// Relocation**************************************************************************/ElfLinker::Relocation::Relocation(const Section *s, unsigned o, const char *t,                                  const Symbol *v, unsigned a) :    section(s), offset(o), type(t), value(v), add(a){    assert(section != NULL);}/*************************************************************************// ElfLinker**************************************************************************/ElfLinker::ElfLinker() :    bele(&N_BELE_RTP::le_policy),    input(NULL), output(NULL), head(NULL), tail(NULL),    sections(NULL), symbols(NULL), relocations(NULL),    nsections(0), nsections_capacity(0),    nsymbols(0), nsymbols_capacity(0),    nrelocations(0), nrelocations_capacity(0),    reloc_done(false){}ElfLinker::~ElfLinker(){    delete [] input;    delete [] output;    unsigned ic;    for (ic = 0; ic < nsections; ic++)        delete sections[ic];    free(sections);    for (ic = 0; ic < nsymbols; ic++)        delete symbols[ic];    free(symbols);    for (ic = 0; ic < nrelocations; ic++)        delete relocations[ic];    free(relocations);}void ElfLinker::init(const void *pdata_v, int plen){    const upx_byte *pdata = (const upx_byte *) pdata_v;    if (plen >= 16 && memcmp(pdata, "UPX#", 4) == 0)    {        // decompress pre-compressed stub-loader        int method;        unsigned u_len, c_len;        if (pdata[4])        {            method = pdata[4];            u_len = get_le16(pdata + 5);            c_len = get_le16(pdata + 7);            pdata += 9;            assert(9 + c_len == (unsigned) plen);        }        else        {            method = pdata[5];            u_len = get_le32(pdata + 6);            c_len = get_le32(pdata + 10);            pdata += 14;            assert(14 + c_len == (unsigned) plen);        }        assert((unsigned) plen < u_len);        inputlen = u_len;        input = new upx_byte[inputlen + 1];        unsigned new_len = u_len;        int r = upx_decompress(pdata, c_len, input, &new_len, method, NULL);        if (r == UPX_E_OUT_OF_MEMORY)            throwOutOfMemoryException();        if (r != UPX_E_OK || new_len != u_len)            throwBadLoader();    }    else    {        inputlen = plen;        input = new upx_byte[inputlen + 1];        memcpy(input, pdata, inputlen);    }    input[inputlen] = 0; // NUL terminate    output = new upx_byte[inputlen];    outputlen = 0;    int pos = find(input, inputlen, "Sections:\n", 10);    assert(pos != -1);    char *psections = (char *) input + pos;    char *psymbols = strstr(psections, "SYMBOL TABLE:\n");    assert(psymbols != NULL);    char *prelocs = strstr(psymbols, "RELOCATION RECORDS FOR ");    assert(prelocs != NULL);    preprocessSections(psections, psymbols);    preprocessSymbols(psymbols, prelocs);    preprocessRelocations(prelocs, (char*) input + inputlen);    addLoader("*UND*");}void ElfLinker::preprocessSections(char *start, char *end){    nsections = 0;    while (start < end)    {        char name[1024];        unsigned offset, size, align;        char *nextl = strchr(start, '\n');        assert(nextl != NULL);        if (sscanf(start, "%*d %1023s %x %*d %*d %x 2**%d",                   name, &size, &offset, &align) == 4)        {            char *n = strstr(start, name);            n[strlen(name)] = 0;            addSection(n, input + offset, size, align);            //printf("section %s preprocessed\n", n);        }        start = nextl + 1;    }    addSection("*ABS*", NULL, 0, 0);    addSection("*UND*", NULL, 0, 0);}void ElfLinker::preprocessSymbols(char *start, char *end){    nsymbols = 0;    while (start < end)    {        char section[1024];        char symbol[1024];        unsigned value, offset;        char *nextl = strchr(start, '\n');        assert(nextl != NULL);        if (sscanf(start, "%x g *ABS* %x %1023s",                   &value, &offset, symbol) == 3)        {            char *s = strstr(start, symbol);            s[strlen(symbol)] = 0;            addSymbol(s, "*ABS*", value);            assert(offset == 0);        }#if 0        else if (sscanf(start, "%x%*8c %1023s %*x %1023s",#else        // work around broken scanf implementations        else if (sscanf(start, "%x%*c%*c%*c%*c%*c%*c%*c%*c %1023s %*x %1023s",#endif                        &offset, section, symbol) == 3)        {            char *s = strstr(start, symbol);            s[strlen(symbol)] = 0;            if (strcmp(section, "*UND*") == 0)                offset = 0xdeaddead;            assert(strcmp(section, "*ABS*") != 0);            addSymbol(s, section, offset);        }        start = nextl + 1;    }}void ElfLinker::preprocessRelocations(char *start, char *end){    char sect[1024];    Section *section = NULL;    nrelocations = 0;    while (start < end)    {        if (sscanf(start, "RELOCATION RECORDS FOR [%[^]]", sect) == 1)            section = findSection(sect);        unsigned offset;        char type[100];        char symbol[1024];        char *nextl = strchr(start, '\n');        assert(nextl != NULL);        if (sscanf(start, "%x %99s %1023s",                   &offset, type, symbol) == 3)        {            char *t = strstr(start, type);            t[strlen(type)] = 0;            unsigned add = 0;            if (char *p = strstr(symbol, "+0x"))            {                *p = 0;  // terminate the symbol name                p += 3;                if (strlen(p) == 16) {                    // skip 8 leading chars if sign of char 9 matches                    if (memcmp(p, "000000000", 9))                        p += 8;                    else if (memcmp(p, "fffffffff", 9))                        p += 8;                }                assert(strlen(p) == 8);                char *endptr = NULL;                unsigned long ul = strtoul(p, &endptr, 16);                add = (unsigned) ul;                assert(add == ul);                assert(endptr && *endptr == '\0');            }            addRelocation(section->name, offset, t, symbol, add);            //printf("relocation %s %s %x %d preprocessed\n", section->name, symbol, offset, add);        }        start = nextl + 1;    }}ElfLinker::Section *ElfLinker::findSection(const char *name, bool fatal) const{    for (unsigned ic = 0; ic < nsections; ic++)        if (strcmp(sections[ic]->name, name) == 0)            return sections[ic];    if (fatal)    {        printf("unknown section %s\n", name);        abort();    }    return NULL;}ElfLinker::Symbol *ElfLinker::findSymbol(const char *name, bool fatal) const{    for (unsigned ic = 0; ic < nsymbols; ic++)        if (strcmp(symbols[ic]->name, name) == 0)            return symbols[ic];    if (fatal)    {        printf("unknown symbol %s\n", name);        abort();    }    return NULL;}ElfLinker::Section *ElfLinker::addSection(const char *sname, const void *sdata, int slen, unsigned p2align){    //printf("addSection: %s len=%d align=%d\n", sname, slen, p2align);    if (update_capacity(nsections, &nsections_capacity))        sections = static_cast<Section **>(realloc(sections, nsections_capacity * sizeof(Section *)));    assert(sections);    assert(sname); assert(sname[0]); assert(sname[strlen(sname)-1] != ':');    assert(findSection(sname, false) == NULL);    Section *sec = new Section(sname, sdata, slen, p2align);    sections[nsections++] = sec;    return sec;}ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section,                                        unsigned offset){    //printf("addSymbol: %s %s 0x%x\n", name, section, offset);    if (update_capacity(nsymbols, &nsymbols_capacity))        symbols = static_cast<Symbol **>(realloc(symbols, nsymbols_capacity * sizeof(Symbol *)));    assert(symbols != NULL);    assert(name); assert(name[0]); assert(name[strlen(name)-1] != ':');    assert(findSymbol(name, false) == NULL);    Symbol *sym = new Symbol(name, findSection(section), offset);    symbols[nsymbols++] = sym;    return sym;}ElfLinker::Relocation *ElfLinker::addRelocation(const char *section, unsigned off,                                                const char *type, const char *symbol,                                                unsigned add){    if (update_capacity(nrelocations, &nrelocations_capacity))        relocations = static_cast<Relocation **>(realloc(relocations, (nrelocations_capacity) * sizeof(Relocation *)));    assert(relocations != NULL);    Relocation *rel = new Relocation(findSection(section), off,                                     type, findSymbol(symbol), add);    relocations[nrelocations++] = rel;    return rel;}#if 0void ElfLinker::setLoaderAlignOffset(int phase){    //assert(phase & 0);    printf("\nFIXME: ElfLinker::setLoaderAlignOffset %d\n", phase);}#endifint ElfLinker::addLoader(const char *sname){    assert(sname != NULL);    if (!sname[0])        return outputlen;    char *begin = strdup(sname);    char *end = begin + strlen(begin);    for (char *sect = begin; sect < end; )    {        for (char *tokend = sect; *tokend; tokend++)            if (*tokend == ' ' || *tokend == ',')            {                *tokend = 0;                break;            }        if (sect[0] == '+') // alignment        {            assert(tail);            unsigned l = (hex(sect[2]) - tail->offset - tail->size) % hex(sect[1]);            if (l)            {                if (sect[3] == 'D')                    alignData(l);                else                    alignCode(l);                tail->size += l;            }        }        else        {            Section *section = findSection(sect);            if (section->p2align) {                assert(tail);                assert(tail != section);                unsigned const v = ~0u << section->p2align;                if (unsigned const l = ~v & (0u-(tail->offset + tail->size))) {                    alignCode(l);                    tail->size += l;                }            }            memcpy(output + outputlen, section->input, section->size);            section->output = output + outputlen;            //printf("section added: 0x%04x %3d %s\n", outputlen, section->size, section->name);            outputlen += section->size;            if (head)            {                tail->next = section;                section->offset = tail->offset + tail->size;            }            else                head = section;            tail = section;        }        sect += strlen(sect) + 1;    }    free(begin);    return outputlen;}void ElfLinker::addLoader(const char *s, va_list ap){    while (s != NULL)    {        addLoader(s);        s = va_arg(ap, const char *);    }}void __acc_cdecl_va ElfLinker::addLoaderVA(const char *s, ...){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -