|
Server : Apache/2.2.17 (Unix) mod_ssl/2.2.17 OpenSSL/0.9.8e-fips-rhel5 DAV/2 PHP/5.2.17 System : Linux localhost 2.6.18-419.el5 #1 SMP Fri Feb 24 22:47:42 UTC 2017 x86_64 User : nobody ( 99) PHP Version : 5.2.17 Disable Function : NONE Directory : /proc/21573/root/lib/modules/2.6.18-419.el5/build/scripts/modsign/ |
Upload File : |
/* mod-extract.c: module extractor for signing
*
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <elf.h>
#include <asm/byteorder.h>
void extract_elf64(void *buffer, size_t size, Elf64_Ehdr *hdr);
void extract_elf32(void *buffer, size_t size, Elf32_Ehdr *hdr);
struct byteorder {
uint16_t (*get16)(const uint16_t *);
uint32_t (*get32)(const uint32_t *);
uint64_t (*get64)(const uint64_t *);
void (*set16)(uint16_t *, uint16_t);
void (*set32)(uint32_t *, uint32_t);
void (*set64)(uint64_t *, uint64_t);
};
uint16_t get16_le(const uint16_t *p) { return __le16_to_cpu(*p); }
uint32_t get32_le(const uint32_t *p) { return __le32_to_cpu(*p); }
uint64_t get64_le(const uint64_t *p) { return __le64_to_cpu(*p); }
uint16_t get16_be(const uint16_t *p) { return __be16_to_cpu(*p); }
uint32_t get32_be(const uint32_t *p) { return __be32_to_cpu(*p); }
uint64_t get64_be(const uint64_t *p) { return __be64_to_cpu(*p); }
void set16_le(uint16_t *p, uint16_t n) { *p = __cpu_to_le16(n); }
void set32_le(uint32_t *p, uint32_t n) { *p = __cpu_to_le32(n); }
void set64_le(uint64_t *p, uint64_t n) { *p = __cpu_to_le64(n); }
void set16_be(uint16_t *p, uint16_t n) { *p = __cpu_to_be16(n); }
void set32_be(uint32_t *p, uint32_t n) { *p = __cpu_to_be32(n); }
void set64_be(uint64_t *p, uint64_t n) { *p = __cpu_to_be64(n); }
const struct byteorder byteorder_le = {
get16_le, get32_le, get64_le,
set16_le, set32_le, set64_le
};
const struct byteorder byteorder_be = {
get16_be, get32_be, get64_be,
set16_be, set32_be, set64_be
};
const struct byteorder *order;
uint16_t get16(const uint16_t *p) { return order->get16(p); }
uint32_t get32(const uint32_t *p) { return order->get32(p); }
uint64_t get64(const uint64_t *p) { return order->get64(p); }
void set16(uint16_t *p, uint16_t n) { order->set16(p, n); }
void set32(uint32_t *p, uint32_t n) { order->set32(p, n); }
void set64(uint64_t *p, uint64_t n) { order->set64(p, n); }
FILE *outfd;
uint8_t csum, xcsum;
void write_out(const void *data, size_t size)
{
const uint8_t *p = data;
size_t loop;
for (loop = 0; loop < size; loop++) {
csum += p[loop];
xcsum += p[loop];
}
if (fwrite(data, 1, size, outfd) != size) {
perror("write");
exit(1);
}
}
#define write_out_val(VAL) write_out(&(VAL), sizeof(VAL))
int is_verbose;
void verbose(const char *fmt, ...) __attribute__((format(printf,1,2)));
void verbose(const char *fmt, ...)
{
va_list va;
if (is_verbose) {
va_start(va, fmt);
vprintf(fmt, va);
va_end(va);
}
}
void usage(void) __attribute__((noreturn));
void usage(void)
{
fprintf(stderr, "Usage: mod-extract [-v] <modulefile> <extractfile>\n");
exit(2);
}
/*****************************************************************************/
/*
*
*/
int main(int argc, char **argv)
{
struct stat st;
Elf32_Ehdr *hdr32;
Elf64_Ehdr *hdr64;
size_t len;
void *buffer;
int fd, be, b64;
while (argc > 1 && strcmp("-v", argv[1]) == 0) {
argv++;
argc--;
is_verbose++;
}
if (argc != 3)
usage();
/* map the module into memory */
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open input");
exit(1);
}
if (fstat(fd, &st) < 0) {
perror("fstat");
exit(1);
}
len = st.st_size;
buffer = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
if (buffer == MAP_FAILED) {
perror("mmap");
exit(1);
}
if (close(fd) < 0) {
perror("close input");
exit(1);
}
/* check it's an ELF object */
hdr32 = buffer;
hdr64 = buffer;
if (hdr32->e_ident[EI_MAG0] != ELFMAG0 ||
hdr32->e_ident[EI_MAG1] != ELFMAG1 ||
hdr32->e_ident[EI_MAG2] != ELFMAG2 ||
hdr32->e_ident[EI_MAG3] != ELFMAG3
) {
fprintf(stderr, "Module does not appear to be ELF\n");
exit(3);
}
/* determine endianness and word size */
b64 = (hdr32->e_ident[EI_CLASS] == ELFCLASS64);
be = (hdr32->e_ident[EI_DATA] == ELFDATA2MSB);
order = be ? &byteorder_be : &byteorder_le;
verbose("Module is %s-bit %s-endian\n",
b64 ? "64" : "32",
be ? "big" : "little");
/* open the output file */
outfd = fopen(argv[2], "w");
if (!outfd) {
perror("open output");
exit(1);
}
/* perform the extraction */
if (b64)
extract_elf64(buffer, len, hdr64);
else
extract_elf32(buffer, len, hdr32);
/* done */
if (fclose(outfd) == EOF) {
perror("close output");
exit(1);
}
return 0;
} /* end main() */
/*****************************************************************************/
/*
* extract a RELA table
* - need to canonicalise the entries in case section addition/removal has
* rearranged the symbol table and the section table
*/
void extract_elf64_rela(const void *buffer, int secix, int targetix,
const Elf64_Rela *relatab, size_t nrels,
const Elf64_Sym *symbols, size_t nsyms,
const Elf64_Shdr *sections, size_t nsects, int *canonmap,
const char *strings, size_t nstrings,
const char *sh_name)
{
struct {
uint64_t r_offset;
uint64_t r_addend;
uint64_t st_value;
uint64_t st_size;
uint32_t r_type;
uint16_t st_shndx;
uint8_t st_info;
uint8_t st_other;
} __attribute__((packed)) relocation;
const Elf64_Sym *symbol;
size_t loop;
/* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
for (loop = 0; loop < nrels; loop++) {
Elf64_Section st_shndx;
Elf64_Xword r_info;
/* decode the relocation */
r_info = get64(&relatab[loop].r_info);
relocation.r_offset = relatab[loop].r_offset;
relocation.r_addend = relatab[loop].r_addend;
set32(&relocation.r_type, ELF64_R_TYPE(r_info));
if (ELF64_R_SYM(r_info) >= nsyms) {
fprintf(stderr, "Invalid symbol ID %lx in relocation %zu\n",
ELF64_R_SYM(r_info), loop);
exit(1);
}
/* decode the symbol referenced by the relocation */
symbol = &symbols[ELF64_R_SYM(r_info)];
relocation.st_info = symbol->st_info;
relocation.st_other = symbol->st_other;
relocation.st_value = symbol->st_value;
relocation.st_size = symbol->st_size;
relocation.st_shndx = symbol->st_shndx;
st_shndx = get16(&symbol->st_shndx);
/* canonicalise the section used by the symbol */
if (st_shndx > SHN_UNDEF && st_shndx < nsects)
set16(&relocation.st_shndx, canonmap[st_shndx]);
write_out_val(relocation);
/* undefined symbols must be named if referenced */
if (st_shndx == SHN_UNDEF) {
const char *name = strings + get32(&symbol->st_name);
write_out(name, strlen(name) + 1);
}
}
verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
} /* end extract_elf64_rela() */
/*****************************************************************************/
/*
* extract a REL table
* - need to canonicalise the entries in case section addition/removal has
* rearranged the symbol table and the section table
*/
void extract_elf64_rel(const void *buffer, int secix, int targetix,
const Elf64_Rel *relatab, size_t nrels,
const Elf64_Sym *symbols, size_t nsyms,
const Elf64_Shdr *sections, size_t nsects, int *canonmap,
const char *strings, size_t nstrings,
const char *sh_name)
{
struct {
uint64_t r_offset;
uint64_t st_value;
uint64_t st_size;
uint32_t r_type;
uint16_t st_shndx;
uint8_t st_info;
uint8_t st_other;
} __attribute__((packed)) relocation;
const Elf64_Sym *symbol;
size_t loop;
/* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
for (loop = 0; loop < nrels; loop++) {
Elf64_Section st_shndx;
Elf64_Xword r_info;
/* decode the relocation */
r_info = get64(&relatab[loop].r_info);
relocation.r_offset = relatab[loop].r_offset;
set32(&relocation.r_type, ELF64_R_TYPE(r_info));
if (ELF64_R_SYM(r_info) >= nsyms) {
fprintf(stderr, "Invalid symbol ID %lx in relocation %zi\n",
ELF64_R_SYM(r_info), loop);
exit(1);
}
/* decode the symbol referenced by the relocation */
symbol = &symbols[ELF64_R_SYM(r_info)];
relocation.st_info = symbol->st_info;
relocation.st_other = symbol->st_other;
relocation.st_value = symbol->st_value;
relocation.st_size = symbol->st_size;
relocation.st_shndx = symbol->st_shndx;
st_shndx = get16(&symbol->st_shndx);
/* canonicalise the section used by the symbol */
if (st_shndx > SHN_UNDEF && st_shndx < nsects)
set16(&relocation.st_shndx, canonmap[st_shndx]);
write_out_val(relocation);
/* undefined symbols must be named if referenced */
if (st_shndx == SHN_UNDEF) {
const char *name = strings + get32(&symbol->st_name);
write_out(name, strlen(name) + 1);
}
}
verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
} /* end extract_elf64_rel() */
/*****************************************************************************/
/*
* extract the data from a 64-bit module
*/
void extract_elf64(void *buffer, size_t len, Elf64_Ehdr *hdr)
{
const Elf64_Sym *symbols;
Elf64_Shdr *sections;
const char *secstrings, *strings;
size_t nsyms, nstrings;
int loop, shnum, *canonlist, *canonmap, canon, changed, tmp;
sections = buffer + get64(&hdr->e_shoff);
secstrings = buffer + get64(§ions[get16(&hdr->e_shstrndx)].sh_offset);
shnum = get16(&hdr->e_shnum);
/* find the symbol table and the string table and produce a list of
* index numbers of sections that contribute to the kernel's module
* image
*/
canonlist = calloc(sizeof(int), shnum * 2);
if (!canonlist) {
perror("calloc");
exit(1);
}
canonmap = canonlist + shnum;
canon = 0;
symbols = NULL;
strings = NULL;
for (loop = 1; loop < shnum; loop++) {
const char *sh_name = secstrings + get32(§ions[loop].sh_name);
Elf64_Word sh_type = get32(§ions[loop].sh_type);
Elf64_Xword sh_size = get64(§ions[loop].sh_size);
Elf64_Xword sh_flags = get64(§ions[loop].sh_flags);
Elf64_Off sh_offset = get64(§ions[loop].sh_offset);
void *data = buffer + sh_offset;
/* quick sanity check */
if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) {
fprintf(stderr, "Section goes beyond EOF\n");
exit(3);
}
/* we only need to canonicalise allocatable sections */
if (sh_flags & SHF_ALLOC)
canonlist[canon++] = loop;
/* keep track of certain special sections */
switch (sh_type) {
case SHT_SYMTAB:
if (strcmp(sh_name, ".symtab") == 0) {
symbols = data;
nsyms = sh_size / sizeof(Elf64_Sym);
}
break;
case SHT_STRTAB:
if (strcmp(sh_name, ".strtab") == 0) {
strings = data;
nstrings = sh_size;
}
break;
default:
break;
}
}
if (!symbols) {
fprintf(stderr, "Couldn't locate symbol table\n");
exit(3);
}
if (!strings) {
fprintf(stderr, "Couldn't locate strings table\n");
exit(3);
}
/* canonicalise the index numbers of the contributing section */
do {
changed = 0;
for (loop = 0; loop < canon - 1; loop++) {
const char *x = secstrings + get32(§ions[canonlist[loop + 0]].sh_name);
const char *y = secstrings + get32(§ions[canonlist[loop + 1]].sh_name);
if (strcmp(x, y) > 0) {
tmp = canonlist[loop + 0];
canonlist[loop + 0] = canonlist[loop + 1];
canonlist[loop + 1] = tmp;
changed = 1;
}
}
} while(changed);
for (loop = 0; loop < canon; loop++)
canonmap[canonlist[loop]] = loop + 1;
if (is_verbose > 1) {
printf("\nSection canonicalisation map:\n");
for (loop = 1; loop < shnum; loop++) {
const char *x = secstrings + get32(§ions[loop].sh_name);
printf("%4d %s\n", canonmap[loop], x);
}
printf("\nAllocated section list in canonical order:\n");
for (loop = 0; loop < canon; loop++) {
const char *x = secstrings + get32(§ions[canonlist[loop]].sh_name);
printf("%4d %s\n", canonlist[loop], x);
}
}
memset(canonlist, 0, sizeof(int) * shnum);
/* iterate through the section table looking for sections we want to
* contribute to the signature */
verbose("\n");
verbose("FILE POS CS SECT NAME\n");
verbose("======== == ==== ==============================\n");
for (loop = 1; loop < shnum; loop++) {
const char *sh_name = secstrings + get32(§ions[loop].sh_name);
Elf64_Word sh_type = get32(§ions[loop].sh_type);
Elf64_Xword sh_size = get64(§ions[loop].sh_size);
Elf64_Xword sh_flags = get64(§ions[loop].sh_flags);
Elf64_Word sh_info = get32(§ions[loop].sh_info);
Elf64_Off sh_offset = get64(§ions[loop].sh_offset);
void *data = buffer + sh_offset;
csum = 0;
/* include canonicalised relocation sections */
if (sh_type == SHT_REL || sh_type == SHT_RELA) {
if (sh_info <= 0 && sh_info >= hdr->e_shnum) {
fprintf(stderr,
"Invalid ELF - REL/RELA sh_info does"
" not refer to a valid section\n");
exit(3);
}
if (canonlist[sh_info]) {
Elf32_Word xsh_info;
verbose("%08lx ", ftell(outfd));
set32(&xsh_info, canonmap[sh_info]);
/* write out selected portions of the section
* header */
write_out(sh_name, strlen(sh_name));
write_out_val(sections[loop].sh_type);
write_out_val(sections[loop].sh_flags);
write_out_val(sections[loop].sh_size);
write_out_val(sections[loop].sh_addralign);
write_out_val(xsh_info);
if (sh_type == SHT_RELA)
extract_elf64_rela(buffer, loop, sh_info,
data, sh_size / sizeof(Elf64_Rela),
symbols, nsyms,
sections, shnum, canonmap,
strings, nstrings,
sh_name);
else
extract_elf64_rel(buffer, loop, sh_info,
data, sh_size / sizeof(Elf64_Rel),
symbols, nsyms,
sections, shnum, canonmap,
strings, nstrings,
sh_name);
}
continue;
}
/* include allocatable loadable sections */
if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
goto include_section;
/* not this section */
continue;
include_section:
verbose("%08lx ", ftell(outfd));
/* write out selected portions of the section header */
write_out(sh_name, strlen(sh_name));
write_out_val(sections[loop].sh_type);
write_out_val(sections[loop].sh_flags);
write_out_val(sections[loop].sh_size);
write_out_val(sections[loop].sh_addralign);
/* write out the section data */
write_out(data, sh_size);
verbose("%02x %4d %s\n", csum, loop, sh_name);
/* note the section has been written */
canonlist[loop] = 1;
}
verbose("%08lx (%lu bytes csum 0x%02x)\n",
ftell(outfd), ftell(outfd), xcsum);
} /* end extract_elf64() */
/*****************************************************************************/
/*
* extract a RELA table
* - need to canonicalise the entries in case section addition/removal has
* rearranged the symbol table and the section table
*/
void extract_elf32_rela(const void *buffer, int secix, int targetix,
const Elf32_Rela *relatab, size_t nrels,
const Elf32_Sym *symbols, size_t nsyms,
const Elf32_Shdr *sections, size_t nsects, int *canonmap,
const char *strings, size_t nstrings,
const char *sh_name)
{
struct {
uint32_t r_offset;
uint32_t r_addend;
uint32_t st_value;
uint32_t st_size;
uint16_t st_shndx;
uint8_t r_type;
uint8_t st_info;
uint8_t st_other;
} __attribute__((packed)) relocation;
const Elf32_Sym *symbol;
size_t loop;
/* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
for (loop = 0; loop < nrels; loop++) {
Elf32_Section st_shndx;
Elf32_Word r_info;
/* decode the relocation */
r_info = get32(&relatab[loop].r_info);
relocation.r_offset = relatab[loop].r_offset;
relocation.r_addend = relatab[loop].r_addend;
relocation.r_type = ELF32_R_TYPE(r_info);
if (ELF32_R_SYM(r_info) >= nsyms) {
fprintf(stderr, "Invalid symbol ID %x in relocation %zu\n",
ELF32_R_SYM(r_info), loop);
exit(1);
}
/* decode the symbol referenced by the relocation */
symbol = &symbols[ELF32_R_SYM(r_info)];
relocation.st_info = symbol->st_info;
relocation.st_other = symbol->st_other;
relocation.st_value = symbol->st_value;
relocation.st_size = symbol->st_size;
relocation.st_shndx = symbol->st_shndx;
st_shndx = get16(&symbol->st_shndx);
/* canonicalise the section used by the symbol */
if (st_shndx > SHN_UNDEF && st_shndx < nsects)
set16(&relocation.st_shndx, canonmap[st_shndx]);
write_out_val(relocation);
/* undefined symbols must be named if referenced */
if (st_shndx == SHN_UNDEF) {
const char *name = strings + get32(&symbol->st_name);
write_out(name, strlen(name) + 1);
}
}
verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
} /* end extract_elf32_rela() */
/*****************************************************************************/
/*
* extract a REL table
* - need to canonicalise the entries in case section addition/removal has
* rearranged the symbol table and the section table
*/
void extract_elf32_rel(const void *buffer, int secix, int targetix,
const Elf32_Rel *relatab, size_t nrels,
const Elf32_Sym *symbols, size_t nsyms,
const Elf32_Shdr *sections, size_t nsects, int *canonmap,
const char *strings, size_t nstrings,
const char *sh_name)
{
struct {
uint32_t r_offset;
uint32_t st_value;
uint32_t st_size;
uint16_t st_shndx;
uint8_t r_type;
uint8_t st_info;
uint8_t st_other;
} __attribute__((packed)) relocation;
const Elf32_Sym *symbol;
size_t loop;
/* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
for (loop = 0; loop < nrels; loop++) {
Elf32_Section st_shndx;
Elf32_Word r_info;
/* decode the relocation */
r_info = get32(&relatab[loop].r_info);
relocation.r_offset = relatab[loop].r_offset;
relocation.r_type = ELF32_R_TYPE(r_info);
if (ELF32_R_SYM(r_info) >= nsyms) {
fprintf(stderr, "Invalid symbol ID %x in relocation %zu\n",
ELF32_R_SYM(r_info), loop);
exit(1);
}
/* decode the symbol referenced by the relocation */
symbol = &symbols[ELF32_R_SYM(r_info)];
relocation.st_info = symbol->st_info;
relocation.st_other = symbol->st_other;
relocation.st_value = symbol->st_value;
relocation.st_size = symbol->st_size;
relocation.st_shndx = symbol->st_shndx;
st_shndx = get16(&symbol->st_shndx);
/* canonicalise the section used by the symbol */
if (st_shndx > SHN_UNDEF && st_shndx < nsects)
set16(&relocation.st_shndx, canonmap[st_shndx]);
write_out_val(relocation);
/* undefined symbols must be named if referenced */
if (st_shndx == SHN_UNDEF) {
const char *name = strings + get32(&symbol->st_name);
write_out(name, strlen(name) + 1);
}
}
verbose("%02x %4d %s [canon]\n", csum, secix, sh_name);
} /* end extract_elf32_rel() */
/*****************************************************************************/
/*
* extract the data from a 32-bit module
*/
void extract_elf32(void *buffer, size_t len, Elf32_Ehdr *hdr)
{
const Elf32_Sym *symbols;
Elf32_Shdr *sections;
const char *secstrings, *strings;
size_t nsyms, nstrings;
int loop, shnum, *canonlist, *canonmap, canon, changed, tmp;
sections = buffer + get32(&hdr->e_shoff);
secstrings = buffer + get32(§ions[get16(&hdr->e_shstrndx)].sh_offset);
shnum = get16(&hdr->e_shnum);
/* find the symbol table and the string table and produce a list of
* index numbers of sections that contribute to the kernel's module
* image
*/
canonlist = calloc(sizeof(int), shnum * 2);
if (!canonlist) {
perror("calloc");
exit(1);
}
canonmap = canonlist + shnum;
canon = 0;
symbols = NULL;
strings = NULL;
for (loop = 1; loop < shnum; loop++) {
const char *sh_name = secstrings + get32(§ions[loop].sh_name);
Elf32_Word sh_type = get32(§ions[loop].sh_type);
Elf32_Xword sh_size = get32(§ions[loop].sh_size);
Elf32_Xword sh_flags = get32(§ions[loop].sh_flags);
Elf32_Off sh_offset = get32(§ions[loop].sh_offset);
void *data = buffer + sh_offset;
/* quick sanity check */
if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) {
fprintf(stderr, "Section goes beyond EOF\n");
exit(3);
}
/* we only need to canonicalise allocatable sections */
if (sh_flags & SHF_ALLOC)
canonlist[canon++] = loop;
/* keep track of certain special sections */
switch (sh_type) {
case SHT_SYMTAB:
if (strcmp(sh_name, ".symtab") == 0) {
symbols = data;
nsyms = sh_size / sizeof(Elf32_Sym);
}
break;
case SHT_STRTAB:
if (strcmp(sh_name, ".strtab") == 0) {
strings = data;
nstrings = sh_size;
}
break;
default:
break;
}
}
if (!symbols) {
fprintf(stderr, "Couldn't locate symbol table\n");
exit(3);
}
if (!strings) {
fprintf(stderr, "Couldn't locate strings table\n");
exit(3);
}
/* canonicalise the index numbers of the contributing section */
do {
changed = 0;
for (loop = 0; loop < canon - 1; loop++) {
const char *x = secstrings + get32(§ions[canonlist[loop + 0]].sh_name);
const char *y = secstrings + get32(§ions[canonlist[loop + 1]].sh_name);
if (strcmp(x, y) > 0) {
tmp = canonlist[loop + 0];
canonlist[loop + 0] = canonlist[loop + 1];
canonlist[loop + 1] = tmp;
changed = 1;
}
}
} while(changed);
for (loop = 0; loop < canon; loop++)
canonmap[canonlist[loop]] = loop + 1;
if (is_verbose > 1) {
printf("\nSection canonicalisation map:\n");
for (loop = 1; loop < shnum; loop++) {
const char *x = secstrings + get32(§ions[loop].sh_name);
printf("%4d %s\n", canonmap[loop], x);
}
printf("\nAllocated section list in canonical order:\n");
for (loop = 0; loop < canon; loop++) {
const char *x = secstrings + get32(§ions[canonlist[loop]].sh_name);
printf("%4d %s\n", canonlist[loop], x);
}
}
memset(canonlist, 0, sizeof(int) * shnum);
/* iterate through the section table looking for sections we want to
* contribute to the signature */
verbose("\n");
verbose("FILE POS CS SECT NAME\n");
verbose("======== == ==== ==============================\n");
for (loop = 1; loop < shnum; loop++) {
const char *sh_name = secstrings + get32(§ions[loop].sh_name);
Elf32_Word sh_type = get32(§ions[loop].sh_type);
Elf32_Xword sh_size = get32(§ions[loop].sh_size);
Elf32_Xword sh_flags = get32(§ions[loop].sh_flags);
Elf32_Word sh_info = get32(§ions[loop].sh_info);
Elf32_Off sh_offset = get32(§ions[loop].sh_offset);
void *data = buffer + sh_offset;
csum = 0;
/* quick sanity check */
if (sh_type != SHT_NOBITS && len < sh_offset + sh_size) {
fprintf(stderr, "section goes beyond EOF\n");
exit(3);
}
/* include canonicalised relocation sections */
if (sh_type == SHT_REL || sh_type == SHT_RELA) {
if (sh_info <= 0 && sh_info >= hdr->e_shnum) {
fprintf(stderr,
"Invalid ELF - REL/RELA sh_info does"
" not refer to a valid section\n");
exit(3);
}
if (canonlist[sh_info]) {
Elf32_Word xsh_info;
verbose("%08lx ", ftell(outfd));
set32(&xsh_info, canonmap[sh_info]);
/* write out selected portions of the section header */
write_out(sh_name, strlen(sh_name));
write_out_val(sections[loop].sh_type);
write_out_val(sections[loop].sh_flags);
write_out_val(sections[loop].sh_size);
write_out_val(sections[loop].sh_addralign);
write_out_val(xsh_info);
if (sh_type == SHT_RELA)
extract_elf32_rela(buffer, loop, sh_info,
data, sh_size / sizeof(Elf32_Rela),
symbols, nsyms,
sections, shnum, canonmap,
strings, nstrings,
sh_name);
else
extract_elf32_rel(buffer, loop, sh_info,
data, sh_size / sizeof(Elf32_Rel),
symbols, nsyms,
sections, shnum, canonmap,
strings, nstrings,
sh_name);
}
continue;
}
/* include allocatable loadable sections */
if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
goto include_section;
/* not this section */
continue;
include_section:
verbose("%08lx ", ftell(outfd));
/* write out selected portions of the section header */
write_out(sh_name, strlen(sh_name));
write_out_val(sections[loop].sh_type);
write_out_val(sections[loop].sh_flags);
write_out_val(sections[loop].sh_size);
write_out_val(sections[loop].sh_addralign);
/* write out the section data */
write_out(data, sh_size);
verbose("%02x %4d %s\n", csum, loop, sh_name);
/* note the section has been written */
canonlist[loop] = 1;
}
verbose("%08lx (%lu bytes csum 0x%02x)\n",
ftell(outfd), ftell(outfd), xcsum);
} /* end extract_elf32() */