FreeCalypso > hg > tcs211-patches
view tool/coff.c @ 17:1fffae285c85
main-pirelli.patch created
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Tue, 08 Sep 2015 01:56:42 +0000 |
parents | 87e9f30f5f86 |
children |
line wrap: on
line source
/* * This C module implements COFF operations for ti-libpatch. */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #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); }