# HG changeset patch # User Space Falcon # Date 1433566275 0 # Node ID 87e9f30f5f865e0af0e133f87fb7279879de7202 # Parent 5ba13fd0e73760c316c01cd74b8bd8caada2164f ti-libpatch: patching implemented diff -r 5ba13fd0e737 -r 87e9f30f5f86 tool/Makefile --- a/tool/Makefile Sat Jun 06 03:16:28 2015 +0000 +++ b/tool/Makefile Sat Jun 06 04:51:15 2015 +0000 @@ -1,8 +1,8 @@ CC= gcc CFLAGS= -O2 PROG= ti-libpatch -OBJS= archive.o globals.o main.o readspec.o -HDRS= ar.h globals.h patchinfo.h +OBJS= archive.o coff.o globals.o main.o patchhook.o readspec.o +HDRS= ar.h coffstruct.h globals.h patchinfo.h all: ${PROG} diff -r 5ba13fd0e737 -r 87e9f30f5f86 tool/archive.c --- a/tool/archive.c Sat Jun 06 03:16:28 2015 +0000 +++ b/tool/archive.c Sat Jun 06 04:51:15 2015 +0000 @@ -70,7 +70,7 @@ lib_in_filename, member_name); exit(1); } - /* the patch hook will go here */ + patch_hook(); /* write it out */ fwrite(&ar_hdr, sizeof(struct ar_hdr), 1, outf); fwrite(member_body, 1, member_size, outf); diff -r 5ba13fd0e737 -r 87e9f30f5f86 tool/coff.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/coff.c Sat Jun 06 04:51:15 2015 +0000 @@ -0,0 +1,141 @@ +/* + * This C module implements COFF operations for ti-libpatch. + */ + +#include +#include +#include +#include +#include +#include "coffstruct.h" +#include "patchinfo.h" +#include "globals.h" + +struct external_scnhdr *sections_raw; +unsigned nsections; +unsigned strtab_offset; + +static unsigned +get_u16(ptr) + u_char *ptr; +{ + return ptr[0] | ptr[1] << 8; +} + +static unsigned +get_u32(ptr) + u_char *ptr; +{ + return ptr[0] | ptr[1] << 8 | ptr[2] << 16 | ptr[3] << 24; +} + +parse_coff_hdr() +{ + struct external_filehdr *filehdr_struct; + unsigned symtab_offset; + unsigned nsymtab; + + filehdr_struct = (struct external_filehdr *) member_body; + if (get_u16(filehdr_struct->f_magic) != 0xC2) { + fprintf(stderr, + "error: member \"%s\" is not a TI COFF2 object\n", + member_name); + exit(1); + } + if (get_u16(filehdr_struct->f_target_id) != 0x97) { + fprintf(stderr, "error: member \"%s\" is not a TMS470 object\n", + member_name); + exit(1); + } + if (get_u16(filehdr_struct->f_opthdr)) { + fprintf(stderr, + "error: member \"%s\" has the \"optional\" header present\n", + member_name); + exit(1); + } + sections_raw = (struct external_scnhdr *) + (member_body + sizeof(struct external_filehdr)); + nsections = get_u16(filehdr_struct->f_nscns); + symtab_offset = get_u32(filehdr_struct->f_symptr); + nsymtab = get_u32(filehdr_struct->f_nsyms); + strtab_offset = symtab_offset + + sizeof(struct external_syment) * nsymtab; + return(0); +} + +static struct external_scnhdr * +find_section_shortname(soughtname) + char *soughtname; +{ + unsigned i; + struct external_scnhdr *scnhdr; + + for (i = 0; i < nsections; i++) { + scnhdr = sections_raw + i; + if (!strncmp(scnhdr->s_name, soughtname, 8)) + return(scnhdr); + } + return(0); +} + +static struct external_scnhdr * +find_section_longname(soughtname) + char *soughtname; +{ + unsigned i; + struct external_scnhdr *scnhdr; + u_char *np, *longname; + + for (i = 0; i < nsections; i++) { + scnhdr = sections_raw + i; + np = scnhdr->s_name; + if (np[0] || np[1] || np[2] || np[3]) + continue; + longname = member_body + strtab_offset + get_u32(np + 4); + if (!strcmp(longname, soughtname)) + return(scnhdr); + } + return(0); +} + +static struct external_scnhdr * +find_section(soughtname) + char *soughtname; +{ + if (strlen(soughtname) <= 8) + return find_section_shortname(soughtname); + else + return find_section_longname(soughtname); +} + +apply_patch(patch) + struct patch_desc *patch; +{ + struct external_scnhdr *scnhdr; + unsigned data_offset, section_size; + + scnhdr = find_section(patch->section); + if (!scnhdr) { + fprintf(stderr, + "error: could not find section \"%s\" in member \"%s\"\n", + patch->section, member_name); + exit(1); + } + data_offset = get_u32(scnhdr->s_scnptr); + section_size = get_u32(scnhdr->s_size); + if (data_offset + section_size > member_size) { + fprintf(stderr, + "error: section \"%s\" in member \"%s\" exceeds member size\n", + patch->section, member_name); + exit(1); + } + if (patch->offset >= section_size) { + fprintf(stderr, + "error: patch offset 0x%x in section \"%s\" exceeds section size\n", + patch->offset, patch->section); + exit(1); + } + /* do it! */ + member_body[data_offset + patch->offset] = patch->new_byte; + return(0); +} diff -r 5ba13fd0e737 -r 87e9f30f5f86 tool/coffstruct.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/coffstruct.h Sat Jun 06 04:51:15 2015 +0000 @@ -0,0 +1,46 @@ +/* + * Here we are going to define the structures found in the COFF artifact + * file to be analyzed. + */ + +struct external_filehdr { + u_char f_magic[2]; /* magic number */ + u_char f_nscns[2]; /* number of sections */ + u_char f_timdat[4]; /* time & date stamp */ + u_char f_symptr[4]; /* file pointer to symtab */ + u_char f_nsyms[4]; /* number of symtab entries */ + u_char f_opthdr[2]; /* sizeof(optional hdr) */ + u_char f_flags[2]; /* flags */ + u_char f_target_id[2]; /* magic no. (TI COFF-specific) */ +}; + +struct external_scnhdr { + u_char s_name[8]; /* section name */ + u_char s_paddr[4]; /* physical address, aliased s_nlib */ + u_char s_vaddr[4]; /* virtual address */ + u_char s_size[4]; /* section size (in WORDS) */ + u_char s_scnptr[4]; /* file ptr to raw data for section */ + u_char s_relptr[4]; /* file ptr to relocation */ + u_char s_lnnoptr[4]; /* file ptr to line numbers */ + u_char s_nreloc[4]; /* number of relocation entries */ + u_char s_nlnno[4]; /* number of line number entries*/ + u_char s_flags[4]; /* flags */ + u_char s_reserved[2]; /* reserved */ + u_char s_page[2]; /* section page number (LOAD) */ +}; + +struct external_syment { + u_char e_name[8]; + u_char e_value[4]; + u_char e_scnum[2]; + u_char e_type[2]; + u_char e_sclass; + u_char e_numaux; +}; + +struct external_reloc { + u_char r_vaddr[4]; + u_char r_symndx[4]; + u_char r_reserved[2]; /* extended pmad byte for COFF2 */ + u_char r_type[2]; +}; diff -r 5ba13fd0e737 -r 87e9f30f5f86 tool/patchhook.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool/patchhook.c Sat Jun 06 04:51:15 2015 +0000 @@ -0,0 +1,42 @@ +/* + * This module implements the "patch hook" that checks if an archive member + * needs to be patched and invokes all necessary patch processing. + */ + +#include +#include +#include +#include +#include +#include +#include "ar.h" +#include "globals.h" +#include "patchinfo.h" + +extern struct ar_hdr ar_hdr; + +update_ar_timestamp() +{ + time_t curtime; + + time(&curtime); + sprintf(ar_hdr.ar_date, "%-12lu", (u_long) curtime); +} + +patch_hook() +{ + struct patch_module_desc *pmd; + struct patch_desc *patch; + + for (pmd = patch_module_list; pmd; pmd = pmd->next) + if (!strcmp(pmd->member_name, member_name)) + break; + if (!pmd) + return(0); + /* yes, we need to patch it: start digging into it */ + parse_coff_hdr(); + for (patch = pmd->patches; patch; patch = patch->next) + apply_patch(patch); + update_ar_timestamp(); + return(1); +}