changeset 6:87e9f30f5f86

ti-libpatch: patching implemented
author Space Falcon <falcon@ivan.Harhan.ORG>
date Sat, 06 Jun 2015 04:51:15 +0000
parents 5ba13fd0e737
children 5a6f608173c4
files tool/Makefile tool/archive.c tool/coff.c tool/coffstruct.h tool/patchhook.c
diffstat 5 files changed, 232 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- 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}
 
--- 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);
--- /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 <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);
+}
--- /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];
+};
--- /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 <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+#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);
+}