1 /*
2 * HT Editor
3 * out_sym.cc
4 *
5 * Copyright (C) 1999-2002 Sebastian Biallas (sb@biallas.net)
6 * Copyright (C) 2002 Stefan Weyergraf
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "analy_names.h"
23 #include "htdebug.h"
24 #include "htinfo.h"
25 #include "out_html.h"
26 #include "tools.h"
27 #include "x86dis.h"
28 #include "string.h"
29
30 /*
31 *
32 * Format of .SYM files:
33 * ==========================================================================
34 * 1. Header, see (1)
35 * 2. "seg_count" "Segment tables", see (2)
36 * 3. Terminator ???, see (A)
37 *
38 * (1) Header
39 * ==========================================================================
40 * The header holds the number of symbols+something ('q_count'),
41 * the number of segments ('seg_count') and the module_name.
42 * I dont know what the other fields stand for...
43 * The header always has 32 bytes.
44 *
45 * (2) Segment table (starts 16-byte aligned)
46 * ==========================================================================
47 * (2.1) Segment Header
48 * - number of symbols "n"
49 * - pointer to "Symbol pointer table" see (2.3), relative to start of
50 * this header
51 *
52 * (2.2) Symbol table
53 * - usually has "n+1" entries of "Symbol table entry", see (3)
54 * - first entry usually is segment descriptor (informative)
55 *
56 * (2.3) Symbol pointer table
57 * - consists of "n" entries of 16-bit pointers to a "Symbol table entry"
58 * (pointers are relative to "Segment Header")
59 *
60 * (3) Symbol table entry
61 * ==========================================================================
62 * contains 32-bit integer ("the address"), followed by a counted
63 * (Pascal-style) string ("the name").
64 *
65 * (A) Appendix A - Unsure
66 * ==========================================================================
67 * observed files always had an additional 4 bytes appended.
68 * bytes are either 00,00,00,04 or 00,00,00,06
69 */
70
71 struct ImageSymHeader {
72 uint32 file_size; // in 16-byte blocks
73 uint16 entry_seg;
74 uint16 u0; // 0000
75 uint16 u1; // 0015 (some flags ?, 0014 for 16-bit .SYM ?)
76 uint16 seg_count;
77 uint32 u2; // 04020002 (some flags ?)
78 byte module_name[16];
79 } PACKED;
80
81 struct ImageSymSegHeader {
82 uint16 next_rec_ofs; // in 16-byte blocks (ring list, last points to first)
83 uint16 sym_count;
84 uint16 sym_ptr_table_ptr;
85 uint16 seg_idx;
86 uint32 seg_start;
87 uint32 seg_size;
88 } PACKED;
89
90 struct ImageSymDescriptor {
91 uint32 address;
92 // byte name_len;
93 // name;
94 // ^^^^ pascal string
95 } PACKED;
96
97 /*
98 *
99 */
100
101 #define MAX_BYTES_PER_SEGMENT 0xff00
102 #define MAX_SYMBOLS_PER_SEGMENT 0x4000
103
write_sym(Stream & stream,uint32 addr,const char * name,uint * bytes_written)104 static void write_sym(Stream &stream, uint32 addr, const char *name, uint *bytes_written)
105 {
106 ImageSymDescriptor desc;
107 desc.address = addr;
108 stream.write(&desc, sizeof desc); // FIXME: endianess !
109 stream.writestrp(name);
110 *bytes_written += sizeof desc + 1 + strlen(name);
111 }
112
g(Stream & stream,Symbol * s,uint * bytes_written,uint * symbols_written,uint16 * ptr_table)113 static void g(Stream &stream, Symbol *s, uint *bytes_written, uint *symbols_written, uint16 *ptr_table)
114 {
115 if (*bytes_written >= MAX_BYTES_PER_SEGMENT) return;
116 if (*symbols_written >= MAX_SYMBOLS_PER_SEGMENT) return;
117
118 uint32 addr;
119 if (s->location->addr->byteSize() == sizeof addr) {
120 s->location->addr->putIntoArray((byte*)&addr);
121 // addr -= 0xbff70000; /* FIXME: hack for kernel32.dll */
122 } else {
123 addr = 0;
124 }
125
126 ptr_table[*symbols_written] = *bytes_written;
127 write_sym(stream, addr, s->name, bytes_written);
128
129 (*symbols_written) ++;
130 }
131
align16(File * file,uint * bytes_written)132 static void align16(File *file, uint *bytes_written)
133 {
134 byte c = 0;
135 while (*bytes_written % 16) {
136 file->write(&c, 1);
137 (*bytes_written) ++;
138 }
139 }
140
export_to_sym(Analyser * analy,File * file)141 int export_to_sym(Analyser *analy, File *file)
142 {
143 if ((!analy) || (!file)) return /*HTML_OUTPUT_ERR_GENERIC*/1;
144 if (analy->active) return /*HTML_OUTPUT_ERR_ANALY_NOT_FINISHED*/1;
145
146 const char *module_name = "TEST";
147 ImageSymHeader head;
148 ImageSymSegHeader seg_head;
149
150 // write dummy header
151 memset(&head, 0, sizeof head);
152 file->write(&head, sizeof head);
153
154
155 /* foreach ($seg) { */
156
157 // write dummy seg header
158 memset(&seg_head, 0, sizeof seg_head);
159 file->write(&seg_head, sizeof seg_head);
160
161 uint bytes_written = sizeof seg_head, symbols_written = 0;
162
163 write_sym(*file, 0xff000000, "_TEXT", &bytes_written);
164
165 uint16 *ptr_table = ht_malloc(MAX_SYMBOLS_PER_SEGMENT * sizeof *ptr_table);
166
167 Symbol *sym = NULL;
168 while ((sym = analy->enumSymbols(sym))) {
169 g(*file, sym, &bytes_written, &symbols_written, ptr_table);
170 }
171
172 uint sym_ptr_table_ptr = bytes_written;
173
174 // FIXME: endianess !
175 file->write(ptr_table, sizeof *ptr_table * symbols_written);
176 bytes_written += sizeof *ptr_table * symbols_written;
177 free(ptr_table);
178
179 align16(file, &bytes_written);
180
181 // FIXME: wrong code order, endianess !
182 uint32 terminator = 0x04000000;
183 file->write(&terminator, sizeof terminator);
184 bytes_written += 4;
185
186 file->seek(0x0020);
187 // write segment header
188 seg_head.next_rec_ofs = 0x0002;
189 seg_head.sym_count = symbols_written;
190 seg_head.sym_ptr_table_ptr = sym_ptr_table_ptr;
191 seg_head.seg_idx = 1;
192 seg_head.seg_start = 0;
193 seg_head.seg_size = 0x0000ffff;
194 // FIXME: endianess !
195 file->write(&seg_head, sizeof seg_head);
196
197 /* } */
198
199
200 bytes_written += sizeof head;
201 file->seek(0);
202 // write header
203 head.file_size = (bytes_written-1) / 16;
204 head.entry_seg = 0;
205 head.u0 = 0;
206 head.u1 = 0x0015;
207 head.seg_count = 1;
208 head.u2 = 0x04020002;
209 memcpy(head.module_name, module_name, MIN(strlen(module_name), sizeof head.module_name));
210 // FIXME: endianess !
211 file->write(&head, sizeof head);
212
213 return 0;
214 }
215
216