2 * $Id: unit.c,v 1.4 2007/07/22 13:33:26 khansen Exp $
4 * Revision 1.4 2007/07/22 13:33:26 khansen
5 * convert tabs to whitespaces
7 * Revision 1.3 2004/12/18 17:00:35 kenth
8 * improved error reporting slightly
10 * Revision 1.2 2004/12/16 13:20:07 kenth
13 * Revision 1.1 2004/06/30 07:56:00 kenth
19 * (C) 2004 Kent Hansen
21 * The XORcyst is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version.
26 * The XORcyst is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with The XORcyst; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41 #define SAFE_FREE(m) if ((m) != NULL) { free(m); m = NULL; }
43 /*---------------------------------------------------------------------------*/
46 #define get_1(f) (unsigned char)fgetc(fp)
47 /* Reads a short (big-endian) */
48 static unsigned short get_2(FILE *fp
)
50 unsigned short result
;
51 result
= get_1(fp
) << 8; /* High byte */
52 result
|= get_1(fp
); /* Low byte */
55 /* Reads a 24-bit integer (big-endian) */
56 static unsigned int get_3(FILE *fp
)
59 result
= get_2(fp
) << 8; /* High 16 bits */
60 result
|= get_1(fp
); /* Low byte */
63 /* Reads an int (big-endian) */
64 static unsigned int get_4(FILE *fp
)
67 /* Assumes little-endian machine!! */
68 result
= get_2(fp
) << 16; /* High 16 bits */
69 result
|= get_2(fp
); /* Low 16 bits */
72 /* Reads a string prepended by 8-bit length */
73 static char *get_str_8(FILE *fp
)
76 int len
= get_1(fp
) + 1;
77 s
= (char *)malloc(len
+ 1);
84 /* Reads a string prepended by 16-bit length */
85 static char *get_str_16(FILE *fp
)
88 int len
= get_2(fp
) + 1;
89 s
= (char *)malloc(len
+ 1);
95 #define get_bytes_8(f) (unsigned char *)get_str_8(f)
96 #define get_bytes_16(f) (unsigned char *)get_str_16(f)
98 /*--------------------------------------------------------------------------*/
101 * Reads a constant from file.
102 * @param fp File handle
103 * @param u Unit in which constant is loaded
104 * @param i Index of constant in unit's constant array
106 static void get_const(FILE *fp
, unit
*u
, int i
)
108 constant
*cnst
= &u
->constants
[i
];
109 cnst
->name
= get_str_8(fp
);
110 cnst
->type
= get_1(fp
);
111 switch (cnst
->type
) {
112 case INT_8
: cnst
->integer
= get_1(fp
); cnst
->type
= INTEGER_CONSTANT
; break;
113 case INT_16
: cnst
->integer
= get_2(fp
); cnst
->type
= INTEGER_CONSTANT
; break;
114 case INT_24
: cnst
->integer
= get_3(fp
); cnst
->type
= INTEGER_CONSTANT
; break;
115 case INT_32
: cnst
->integer
= get_4(fp
); cnst
->type
= INTEGER_CONSTANT
; break;
116 case STR_8
: cnst
->string
= get_str_8(fp
); cnst
->type
= STRING_CONSTANT
; break;
117 case STR_16
: cnst
->string
= get_str_16(fp
); cnst
->type
= STRING_CONSTANT
; break;
120 fprintf(stderr
, "%s(0x%lx): get_const(): bad constant type (%.2X)\n", u
->name
, ftell(fp
), cnst
->type
);
127 * Reads constant array from file.
128 * @param fp File handle
129 * @param u Unit whose constants array will be populated
131 static void get_constants(FILE *fp
, unit
*u
)
134 int count
= get_2(fp
);
136 u
->constants
= (constant
*)malloc(sizeof(constant
) * count
);
140 for (i
=0; i
<count
; i
++) {
143 u
->const_count
= count
;
147 * Reads imported symbol from file.
148 * @param fp File handle
150 * @param i External index
152 static void get_ext(FILE *fp
, unit
*u
, int i
)
154 external
*ext
= &u
->externals
[i
];
155 ext
->unit
= get_1(fp
);
156 ext
->name
= get_str_8(fp
);
161 * Reads imported symbol array from file.
162 * @param fp File handle
163 * @param u Unit whose externals array will be populated
165 static void get_externals(FILE *fp
, unit
*u
)
171 u
->externals
= (external
*)malloc(sizeof(external
) * count
);
175 for (i
=0; i
<count
; i
++) {
178 u
->ext_count
= count
;
182 * Reads an expression from file.
183 * @param fp File handle
184 * @param dest Pointer to pointer where expression should be stored
185 * @param u Owner unit
187 static void get_expr_recursive(FILE *fp
, expression
**dest
, unit
*u
)
190 expression
*exp
= (expression
*)malloc( sizeof(expression
) );
194 case INT_8
: exp
->integer
= get_1(fp
); exp
->type
= INTEGER_EXPRESSION
; break;
195 case INT_16
: exp
->integer
= get_2(fp
); exp
->type
= INTEGER_EXPRESSION
; break;
196 case INT_24
: exp
->integer
= get_3(fp
); exp
->type
= INTEGER_EXPRESSION
; break;
197 case INT_32
: exp
->integer
= get_4(fp
); exp
->type
= INTEGER_EXPRESSION
; break;
198 case STR_8
: exp
->string
= get_str_8(fp
); exp
->type
= STRING_EXPRESSION
; break;
199 case STR_16
: exp
->string
= get_str_16(fp
); exp
->type
= STRING_EXPRESSION
; break;
201 case LOCAL
: exp
->local_id
= get_2(fp
); exp
->type
= LOCAL_EXPRESSION
; break;
202 case EXTRN
: exp
->extrn_id
= get_2(fp
); exp
->type
= EXTERNAL_EXPRESSION
;break;
204 case PC
: ; exp
->type
= PC_EXPRESSION
; break;
222 get_expr_recursive(fp
, &exp
->op_expr
.lhs
, u
);
223 get_expr_recursive(fp
, &exp
->op_expr
.rhs
, u
);
224 exp
->op_expr
.operator = type
;
225 exp
->type
= OPERATOR_EXPRESSION
;
234 get_expr_recursive(fp
, &exp
->op_expr
.lhs
, u
);
235 exp
->op_expr
.rhs
= NULL
;
236 exp
->op_expr
.operator = type
;
237 exp
->type
= OPERATOR_EXPRESSION
;
241 fprintf(stderr
, "%s(0x%lx): get_expr(): invalid expression type (%.2X)\n", u
->name
, ftell(fp
), type
);
243 exp
->type
= INTEGER_EXPRESSION
;
252 * Reads expressions from file.
253 * @param fp File handle
254 * @param u Unit whose expressions array to populate
256 static void get_expressions(FILE *fp
, unit
*u
)
262 u
->expressions
= (expression
**)malloc(sizeof(expression
*) * count
);
264 u
->expressions
= NULL
;
266 for (i
=0; i
<count
; i
++) {
267 get_expr_recursive(fp
, &u
->expressions
[i
], u
);
269 u
->expr_count
= count
;
273 * Reads a segment from file.
274 * @param fp File handle
275 * @param seg Where to store segment
277 static void get_segment(FILE *fp
, segment
*seg
)
279 seg
->size
= get_3(fp
);
281 seg
->bytes
= (unsigned char *)malloc(seg
->size
);
282 if (seg
->bytes
!= NULL
) {
283 fread(seg
->bytes
, 1, seg
->size
, fp
);
290 /*--------------------------------------------------------------------------*/
293 * Reads a unit from file.
294 * @param filename Name of the unit
295 * @param u Pointer to struct to fill in
297 int unit_read(char *filename
, unit
*u
)
301 unsigned short magic
;
302 unsigned char version
;
305 fp
= fopen(filename
, "rb");
311 u
->dataseg
.bytes
= NULL
;
313 u
->codeseg
.bytes
= NULL
;
318 if (magic
!= A_MAGIC
) {
319 /* Error, bad magic number */
324 if (version
!= A_VERSION
) {
325 /* Error, bad version */
329 get_constants(fp
, u
);
331 /* Read # of units explicitly imported from */
333 /* Read unit names */
334 for (i
=0; i
<count
; i
++) {
338 get_externals(fp
, u
);
339 get_segment(fp
, &u
->dataseg
);
340 get_segment(fp
, &u
->codeseg
);
341 get_expressions(fp
, u
);
349 /*--------------------------------------------------------------------------*/
352 * Finalizes a constant.
353 * @param c Constant to finalize
355 static void finalize_constant(constant
*c
)
357 if (c
->type
== STRING_CONSTANT
) {
358 SAFE_FREE(c
->string
);
364 * Finalizes an external.
365 * @param e External to finalize
367 static void finalize_external(external
*e
)
373 * Finalizes an expression.
374 * @param e Expression to finalize
376 static void finalize_expression(expression
*e
)
378 if (e
== NULL
) { return; }
380 case STRING_EXPRESSION
:
381 SAFE_FREE(e
->string
);
384 case OPERATOR_EXPRESSION
:
385 finalize_expression(e
->op_expr
.lhs
);
386 finalize_expression(e
->op_expr
.rhs
);
397 * Finalizes a bytecode segment.
398 * @param s Segment to finalize
400 static void finalize_segment(segment
*s
)
405 /*--------------------------------------------------------------------------*/
409 * @param u Unit to finalize
411 void unit_finalize(unit
*u
)
414 for (i
=0; i
<u
->const_count
; i
++) {
415 finalize_constant(&u
->constants
[i
]);
417 SAFE_FREE(u
->constants
);
419 for (i
=0; i
<u
->ext_count
; i
++) {
420 finalize_external(&u
->externals
[i
]);
422 SAFE_FREE(u
->externals
);
424 for (i
=0; i
<u
->expr_count
; i
++) {
425 finalize_expression(u
->expressions
[i
]);
427 SAFE_FREE(u
->expressions
);
429 finalize_segment(&u
->dataseg
);
430 finalize_segment(&u
->codeseg
);