start new makefile, migrate to libpicofe
[picodrive.git] / cpu / Cyclone / epoc / patchtable_symb.c
CommitLineData
cc68a136 1#include <stdio.h>\r
2#include <stdlib.h>\r
3#include <string.h>\r
4\r
5\r
6typedef struct {\r
7 unsigned long _dontcare1[4];\r
8 char signature[4]; // 'EPOC'\r
9 unsigned long iCpu; // 0x1000 = X86, 0x2000 = ARM, 0x4000 = M*Core\r
10 unsigned long iCheckSumCode; // sum of all 32 bit words in .text\r
11 unsigned long _dontcare3[5];\r
12 unsigned long iCodeSize; // size of code, import address table, constant data and export dir |+30\r
13 unsigned long _dontcare4[12];\r
14 unsigned long iCodeOffset; // file offset to code section |+64\r
15 unsigned long _dontcare5[2];\r
16 unsigned long iCodeRelocOffset; // relocations for code and const |+70\r
17 unsigned long iDataRelocOffset; // relocations for data\r
18 unsigned long iPriority; // priority of this process (EPriorityHigh=450)\r
19} E32ImageHeader;\r
20\r
21\r
22typedef struct {\r
23 unsigned long iSize; // size of this relocation section\r
24 unsigned long iNumberOfRelocs; // number of relocations in this section\r
25} E32RelocSection;\r
26\r
27\r
28typedef struct {\r
29 unsigned long base;\r
30 unsigned long size;\r
31} reloc_page_header;\r
32\r
33\r
34// E32Image relocation section consists of a number of pages\r
35// every page has 8 byte header and a number or 16bit relocation entries\r
36// entry format:\r
37// 0x3000 | <12bit_reloc_offset>\r
38//\r
39// if we have page_header.base == 0x1000 and a reloc entry 0x3110,\r
40// it means that 32bit value at offset 0x1110 of .text section\r
41// is relocatable\r
42\r
43int main(int argc, char *argv[])\r
44{\r
45 FILE *f = 0;\r
46 unsigned char pattern[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56 };\r
47 unsigned char *buff, *p;\r
48 unsigned long patt_offset; // pattern offset in .text section\r
49 unsigned long size = 0, i, symbols, insert_pos, *handler;\r
50 unsigned short reloc_entry;\r
51 E32ImageHeader *header;\r
52 E32RelocSection *reloc_section;\r
53 reloc_page_header *reloc_page;\r
54\r
55 if(argc != 3) {\r
56 printf("usage: %s <e32_exe> <nsymbols>\n\n", argv[0]);\r
57 printf("note: this was written to fix a problem caused by as v.2.9-psion-98r2 and shouldn't be used for anything else.\n", argv[0]);\r
58 return 1;\r
59 }\r
60 \r
61 f = fopen(argv[1], "rb+");\r
62 if(!f) {\r
63 printf("%s: couldn't open %s\n", argv[0], argv[1]);\r
64 return 2;\r
65 }\r
66\r
67 symbols = atoi(argv[2]);\r
68\r
69 // read the file\r
70 fseek(f,0,SEEK_END); size=ftell(f); fseek(f,0,SEEK_SET);\r
71 buff = (unsigned char *) malloc(size);\r
72 fread(buff,1,size,f);\r
73\r
74 header = (E32ImageHeader *) buff;\r
75\r
76 if(strncmp(header->signature, "EPOC", 4) || header->iCpu != 0x2000) {\r
77 printf("%s: not a E32 executable image for ARM target.\n", argv[0]);\r
78 fclose(f);\r
79 free(buff);\r
80 return 2;\r
81 }\r
82\r
83 // find the pattern\r
84 for(i = 0; i < size-8; i++)\r
85 if(memcmp(buff+i, pattern, 8) == 0) break;\r
86 if(i == size-8 || i < 4) {\r
87 printf("%s: failed to find the pattern.\n", argv[0]);\r
88 fclose(f);\r
89 free(buff);\r
90 return 3;\r
91 }\r
92 patt_offset = i - header->iCodeOffset;\r
93\r
94 // find suitable reloc section\r
95 reloc_section = (E32RelocSection *) (buff + header->iCodeRelocOffset);\r
96 for(i = 0, p = buff+header->iCodeRelocOffset+8; i < reloc_section->iSize; ) {\r
97 reloc_page = (reloc_page_header *) p;\r
98 if(patt_offset - reloc_page->base >= 0 && patt_offset - reloc_page->base < 0x1000 - symbols*4) break;\r
99 i += reloc_page->size;\r
100 p += reloc_page->size;\r
101 }\r
102\r
103 if(i >= reloc_section->iSize) {\r
104 printf("%s: suitable reloc section not found.\n", argv[0]);\r
105 fclose(f);\r
106 free(buff);\r
107 return 4;\r
108 }\r
109\r
110 // now find the insert pos and update everything\r
111 insert_pos = p + reloc_page->size - buff;\r
112 reloc_page->size += symbols*2;\r
113 reloc_section->iSize += symbols*2;\r
114 reloc_section->iNumberOfRelocs += symbols;\r
115 header->iDataRelocOffset += symbols*2; // data reloc section is now also pushed a little\r
116 header->iPriority = 450; // let's boost our priority :)\r
117\r
118 // replace the placeholders themselves\r
119 handler = (unsigned long *) (buff + patt_offset + header->iCodeOffset - 4);\r
120 for(i = 1; i <= symbols; i++)\r
121 *(handler+i) = *handler;\r
122 \r
123 // recalculate checksum\r
124 header->iCheckSumCode = 0;\r
125 for(i = 0, p = buff+header->iCodeOffset; i < header->iCodeSize; i+=4, p+=4)\r
126 header->iCheckSumCode += *(unsigned long *) p;\r
127\r
128 // check for possible padding\r
129 if(!*(buff+insert_pos-1)) insert_pos -= 2;\r
130\r
131 // write all this joy\r
132 fseek(f,0,SEEK_SET);\r
133 fwrite(buff, 1, insert_pos, f);\r
134\r
135 // write new reloc entries\r
136 for(i = 0; i < symbols; i++) {\r
137 handler++;\r
138 reloc_entry = ((unsigned char *) handler - buff - reloc_page->base - header->iCodeOffset) | 0x3000;\r
139 fwrite(&reloc_entry, 1, 2, f);\r
140 }\r
141\r
142 // write the remaining data\r
143 fwrite(buff+insert_pos, 1, size-insert_pos, f);\r
144\r
145 // done at last!\r
146 fclose(f);\r
147 free(buff);\r
148\r
149 return 0;\r
150}\r