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

📄 linker.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    va_list ap;    va_start(ap, s);    addLoader(s, ap);    va_end(ap);}int ElfLinker::getSection(const char *sname, int *slen) const{    const Section *section = findSection(sname);    if (slen)        *slen = section->size;    return section->output - output;}int ElfLinker::getSectionSize(const char *sname) const{    const Section *section = findSection(sname);    return section->size;}upx_byte *ElfLinker::getLoader(int *llen) const{    if (llen)        *llen = outputlen;    return output;}void ElfLinker::relocate(){    assert(!reloc_done);    reloc_done = true;    for (unsigned ic = 0; ic < nrelocations; ic++)    {        const Relocation *rel = relocations[ic];        unsigned value;        if (rel->section->output == NULL)            continue;        if (strcmp(rel->value->section->name, "*ABS*") == 0)        {            value = rel->value->offset;        }        else if (strcmp(rel->value->section->name, "*UND*") == 0 &&                 rel->value->offset == 0xdeaddead)        {            printf("undefined symbol '%s' referenced\n", rel->value->name);            abort();        }        else if (rel->value->section->output == NULL)        {            printf("can not apply reloc '%s:%x' without section '%s'\n",                   rel->section->name, rel->offset,                   rel->value->section->name);            abort();        }        else        {            value = rel->value->section->offset +                    rel->value->offset + rel->add;        }        upx_byte *location = rel->section->output + rel->offset;        //printf("%-28s %-28s %-10s 0x%08x 0x%08x\n", rel->section->name, rel->value->name, rel->type, value, value - rel->section->offset - rel->offset);        //printf("  %d %d %d %d %d : %d\n", value, rel->value->section->offset, rel->value->offset, rel->offset, rel->add, *location);        relocate1(rel, location, value, rel->type);    }}void ElfLinker::defineSymbol(const char *name, unsigned value){    Symbol *symbol = findSymbol(name);    if (strcmp(symbol->section->name, "*ABS*") == 0)    {        printf("defineSymbol: symbol '%s' is *ABS*\n", name);        abort();    }    else if (strcmp(symbol->section->name, "*UND*") == 0) // for undefined symbols        symbol->offset = value;    else if (strcmp(symbol->section->name, name) == 0) // for sections    {        for (Section *section = symbol->section; section; section = section->next)        {            assert(section->offset < value);            section->offset = value;            value += section->size;        }    }    else    {        printf("defineSymbol: symbol '%s' already defined\n", name);        abort();    }}// debugging supportvoid ElfLinker::dumpSymbol(const Symbol *symbol, unsigned flags, FILE *fp) const{    if ((flags & 1) && symbol->section->output == NULL)        return;    fprintf(fp, "%-28s 0x%08x | %-28s 0x%08x\n",            symbol->name, symbol->offset, symbol->section->name, symbol->section->offset);}void ElfLinker::dumpSymbols(unsigned flags, FILE *fp) const{    if (fp == NULL)        fp = stdout;    if ((flags & 2) == 0)    {        // default: dump symbols in used section order        for (const Section *section = head; section; section = section->next)        {            fprintf(fp, "%-42s%-28s 0x%08x\n", "", section->name, section->offset);            for (unsigned ic = 0; ic < nsymbols; ic++)            {                const Symbol *symbol = symbols[ic];                if (symbol->section == section && strcmp(symbol->name, section->name) != 0)                    dumpSymbol(symbol, flags, fp);            }        }    }    else    {        // dump all symbols        for (unsigned ic = 0; ic < nsymbols; ic++)            dumpSymbol(symbols[ic], flags, fp);    }}unsigned ElfLinker::getSymbolOffset(const char *name) const{    const Symbol *symbol = findSymbol(name);    if (symbol->section->output == NULL)        return 0xdeaddead;    return symbol->section->offset + symbol->offset;}void ElfLinker::alignWithByte(unsigned len, unsigned char b){    memset(output + outputlen, b, len);    outputlen += len;}void ElfLinker::relocate1(const Relocation *rel, upx_byte *,                          unsigned, const char *){    printf("unknown relocation type '%s\n", rel->type);    abort();}/*************************************************************************// ElfLinker arch subclasses// FIXME: add more displacment overflow checks// FIXME: add support for our special "ignore_reloc_overflow" section**************************************************************************/#if 0 // FIXMEstatic void check8(const Relocation *rel, const upx_byte *location, int v, int d){    if (v < -128 || v > 127) {        printf("value out of range (%d) in reloc %s:%x\n",               v, rel->section->name, rel->offset);        abort();    }    if (d < -128 || d > 127) {        printf("displacement target out of range (%d) in reloc %s:%x\n",               v, rel->section->name, rel->offset);        abort();    }}#endifvoid ElfLinkerAMD64::relocate1(const Relocation *rel, upx_byte *location,                               unsigned value, const char *type){    if (strncmp(type, "R_X86_64_", 9))        return super::relocate1(rel, location, value, type);    type += 9;    if (strncmp(type, "PC", 2) == 0)    {        value -= rel->section->offset + rel->offset;        type += 2;    }    if (strcmp(type, "8") == 0)    {#if (ACC_CC_PGI)        int displ = * (signed char *) location + (int) value; // CBUG#else        int displ = (signed char) *location + (int) value;#endif        if (displ < -128 || displ > 127)        {            printf("target out of range (%d) in reloc %s:%x\n",                   displ, rel->section->name, rel->offset);            abort();        }        *location += value;    }    else if (strcmp(type, "16") == 0)        set_le16(location, get_le16(location) + value);    else if (strcmp(type, "32") == 0)        set_le32(location, get_le32(location) + value);    else        super::relocate1(rel, location, value, type);}void ElfLinkerArmBE::relocate1(const Relocation *rel, upx_byte *location,                               unsigned value, const char *type){    if (strcmp(type, "R_ARM_PC24") == 0)    {        value -= rel->section->offset + rel->offset;        set_be24(1+ location, get_be24(1+ location) + value / 4);    }    else if (strcmp(type, "R_ARM_ABS32") == 0)    {        set_be32(location, get_be32(location) + value);    }    else if (strcmp(type, "R_ARM_THM_CALL") == 0)    {        value -= rel->section->offset + rel->offset;        value += ((get_be16(location) & 0x7ff) << 12);        value += (get_be16(location + 2) & 0x7ff) << 1;        set_be16(location, 0xf000 + ((value >> 12) & 0x7ff));        set_be16(location + 2, 0xf800 + ((value >> 1)  & 0x7ff));        //(b, 0xF000 + ((v - 1) / 2) * 0x10000);        //set_be32(location, get_be32(location) + value / 4);    }    else if (0==strcmp("R_ARM_ABS8", type)) {        *location += value;    }    else        super::relocate1(rel, location, value, type);}void ElfLinkerArmLE::relocate1(const Relocation *rel, upx_byte *location,                               unsigned value, const char *type){    if (strcmp(type, "R_ARM_PC24") == 0)    {        value -= rel->section->offset + rel->offset;        set_le24(location, get_le24(location) + value / 4);    }    else if (strcmp(type, "R_ARM_ABS32") == 0)    {        set_le32(location, get_le32(location) + value);    }    else if (strcmp(type, "R_ARM_THM_CALL") == 0)    {        value -= rel->section->offset + rel->offset;        value += ((get_le16(location) & 0x7ff) << 12);        value += (get_le16(location + 2) & 0x7ff) << 1;        set_le16(location, 0xf000 + ((value >> 12) & 0x7ff));        set_le16(location + 2, 0xf800 + ((value >> 1)  & 0x7ff));        //(b, 0xF000 + ((v - 1) / 2) * 0x10000);        //set_le32(location, get_le32(location) + value / 4);    }    else if (0==strcmp("R_ARM_ABS8", type)) {        *location += value;    }    else        super::relocate1(rel, location, value, type);}void ElfLinkerM68k::alignCode(unsigned len){    assert((len & 1) == 0);    assert((outputlen & 1) == 0);    for (unsigned i = 0; i < len; i += 2)        set_be16(output + outputlen + i, 0x4e71); // "nop"    outputlen += len;}void ElfLinkerM68k::relocate1(const Relocation *rel, upx_byte *location,                              unsigned value, const char *type){    if (strncmp(type, "R_68K_", 6))        return super::relocate1(rel, location, value, type);    type += 6;    if (strncmp(type, "PC", 2) == 0)    {        value -= rel->section->offset + rel->offset;        type += 2;    }    if (strcmp(type, "8") == 0) {        *location += value;    }    else if (strcmp(type, "16") == 0) {        set_be16(location, get_be16(location) + value);    }    else if (strcmp(type, "32") == 0) {        set_be32(location, get_be32(location) + value);    }    else        super::relocate1(rel, location, value, type);}void ElfLinkerMipsBE::relocate1(const Relocation *rel, upx_byte *location,                                unsigned value, const char *type){#define MIPS_HI(a)      (((a) >> 16) + (((a) & 0x8000) >> 15))#define MIPS_LO(a)      ((a) & 0xffff)#define MIPS_PC16(a)    ((a) >> 2)#define MIPS_PC26(a)    (((a) & 0x0fffffff) >> 2)    if (strcmp(type, "R_MIPS_HI16") == 0)        set_le16(location, get_le16(location) + MIPS_HI(value));    else if (strcmp(type, "R_MIPS_LO16") == 0)        set_le16(location, get_le16(location) + MIPS_LO(value));    else if (strcmp(type, "R_MIPS_PC16") == 0)    {        value -= rel->section->offset + rel->offset;        set_le16(location, get_le16(location) + MIPS_PC16(value));    }    else if (strcmp(type, "R_MIPS_26") == 0)        set_le32(location, get_le32(location) + MIPS_PC26(value));    else if (strcmp(type, "R_MIPS_32") == 0)        set_le32(location, get_le32(location) + value);    else        super::relocate1(rel, location, value, type);#undef MIPS_HI#undef MIPS_LO#undef MIPS_PC16#undef MIPS_PC26}void ElfLinkerMipsLE::relocate1(const Relocation *rel, upx_byte *location,                                unsigned value, const char *type){#define MIPS_HI(a)      (((a) >> 16) + (((a) & 0x8000) >> 15))#define MIPS_LO(a)      ((a) & 0xffff)#define MIPS_PC16(a)    ((a) >> 2)#define MIPS_PC26(a)    (((a) & 0x0fffffff) >> 2)    if (strcmp(type, "R_MIPS_HI16") == 0)        set_le16(location, get_le16(location) + MIPS_HI(value));    else if (strcmp(type, "R_MIPS_LO16") == 0)        set_le16(location, get_le16(location) + MIPS_LO(value));    else if (strcmp(type, "R_MIPS_PC16") == 0)    {        value -= rel->section->offset + rel->offset;        set_le16(location, get_le16(location) + MIPS_PC16(value));    }    else if (strcmp(type, "R_MIPS_26") == 0)        set_le32(location, get_le32(location) + MIPS_PC26(value));    else if (strcmp(type, "R_MIPS_32") == 0)        set_le32(location, get_le32(location) + value);    else        super::relocate1(rel, location, value, type);#undef MIPS_HI#undef MIPS_LO#undef MIPS_PC16#undef MIPS_PC26}void ElfLinkerPpc32::relocate1(const Relocation *rel, upx_byte *location,                               unsigned value, const char *type){    if (strncmp(type, "R_PPC_", 6))        return super::relocate1(rel, location, value, type);    type += 6;    if (strcmp(type, "ADDR32") == 0)    {        set_be32(location, get_be32(location) + value);        return;    }    if (strncmp(type, "REL", 3) == 0)    {        value -= rel->section->offset + rel->offset;        type += 3;    }    // FIXME: more relocs    // Note that original (*location).displ is ignored.    if (strcmp(type, "24") == 0) {        if (3& value) {            printf("unaligned word diplacement");            abort();        }        // FIXME: displacment overflow?        set_be32(location, (0xfc000003 & get_be32(location)) +            (0x03fffffc & value));    }    else if (strcmp(type, "14") == 0) {        if (3& value) {            printf("unaligned word diplacement");            abort();        }        // FIXME: displacment overflow?        set_be32(location, (0xffff0003 & get_be32(location)) +            (0x0000fffc & value));    }    else        super::relocate1(rel, location, value, type);}void ElfLinkerX86::relocate1(const Relocation *rel, upx_byte *location,                             unsigned value, const char *type){    if (strncmp(type, "R_386_", 6))        return super::relocate1(rel, location, value, type);    type += 6;    bool range_check = false;    if (strncmp(type, "PC", 2) == 0)    {        value -= rel->section->offset + rel->offset;        type += 2;        range_check = true;    }    if (strcmp(type, "8") == 0)    {#if (ACC_CC_PGI)        int displ = * (signed char *) location + (int) value; // CBUG#else        int displ = (signed char) *location + (int) value;#endif        if (range_check && (displ < -128 || displ > 127)) {            printf("target out of range (%d,%d,%d) in reloc %s:%x\n",                   displ, *location, value, rel->section->name, rel->offset);            abort();        }        *location += value;    }    else if (strcmp(type, "16") == 0)        set_le16(location, get_le16(location) + value);    else if (strcmp(type, "32") == 0)        set_le32(location, get_le32(location) + value);    else        super::relocate1(rel, location, value, type);}/*vi:ts=4:et*/

⌨️ 快捷键说明

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