Make output endian-tolerant by making intnum and floatnum output functions for

arch.  This will also simplify other objfmt expr output functions.  Change
file functions to use bits instead of byte/short/long, and create both little
and big endian versions.  This name change caused changes in several other
files.

svn path=/trunk/yasm/; revision=747
0.3
Peter Johnson 23 years ago
parent d1f5de8d45
commit 494ed1738d
  1. 11
      libyasm/arch.h
  2. 2
      libyasm/bytecode.c
  3. 28
      libyasm/file.c
  4. 89
      libyasm/file.h
  5. 2
      libyasm/floatnum.c
  6. 2
      libyasm/intnum.c
  7. 5
      modules/arch/x86/x86arch.c
  8. 6
      modules/arch/x86/x86arch.h
  9. 55
      modules/arch/x86/x86bc.c
  10. 24
      modules/arch/x86/x86expr.c
  11. 54
      modules/objfmts/bin/bin-objfmt.c
  12. 11
      src/arch.h
  13. 5
      src/arch/x86/x86arch.c
  14. 6
      src/arch/x86/x86arch.h
  15. 55
      src/arch/x86/x86bc.c
  16. 24
      src/arch/x86/x86expr.c
  17. 2
      src/bytecode.c
  18. 28
      src/file.c
  19. 89
      src/file.h
  20. 2
      src/floatnum.c
  21. 2
      src/intnum.c
  22. 54
      src/objfmts/bin/bin-objfmt.c

@ -141,6 +141,17 @@ struct arch {
output_expr_func output_expr);
} bc;
/* Functions to output floats and integers, architecture-specific because
* of endianness. Returns nonzero on error, otherwise updates bufp by
* valsize (bytes saved to bufp). For intnums, rel indicates a relative
* displacement, and bc is the containing bytecode to compute it from.
*/
int (*floatnum_tobytes) (const floatnum *flt, unsigned char **bufp,
unsigned long valsize, const expr *e);
int (*intnum_tobytes) (const intnum *intn, unsigned char **bufp,
unsigned long valsize, const expr *e,
const bytecode *bc, int rel);
/* Gets the equivalent register size in bytes. Returns 0 if there is no
* suitable equivalent size.
*/

@ -668,7 +668,7 @@ bc_tobytes_data(bytecode_data *bc_data, unsigned char **bufp,
if (slen > 0) {
slen = bc_data->size-slen;
for (i=0; i<slen; i++)
WRITE_BYTE(*bufp, 0);
WRITE_8(*bufp, 0);
}
break;
}

@ -75,7 +75,7 @@ replace_extension(const char *orig, /*@null@*/ const char *ext,
}
size_t
fwrite_short(unsigned short val, FILE *f)
fwrite_16_l(unsigned short val, FILE *f)
{
if (fputc(val & 0xFF, f) == EOF)
return 0;
@ -85,7 +85,7 @@ fwrite_short(unsigned short val, FILE *f)
}
size_t
fwrite_long(unsigned long val, FILE *f)
fwrite_32_l(unsigned long val, FILE *f)
{
if (fputc((int)(val & 0xFF), f) == EOF)
return 0;
@ -97,3 +97,27 @@ fwrite_long(unsigned long val, FILE *f)
return 0;
return 1;
}
size_t
fwrite_16_b(unsigned short val, FILE *f)
{
if (fputc((val >> 8) & 0xFF, f) == EOF)
return 0;
if (fputc(val & 0xFF, f) == EOF)
return 0;
return 1;
}
size_t
fwrite_32_b(unsigned long val, FILE *f)
{
if (fputc((int)((val >> 24) & 0xFF), f) == EOF)
return 0;
if (fputc((int)((val >> 16) & 0xFF), f) == EOF)
return 0;
if (fputc((int)((val >> 8) & 0xFF), f) == EOF)
return 0;
if (fputc((int)(val & 0xFF), f) == EOF)
return 0;
return 1;
}

@ -1,5 +1,5 @@
/* $IdPath$
* Little-endian file functions header file.
* Big and little endian file functions header file.
*
* Copyright (C) 2001 Peter Johnson
*
@ -33,16 +33,16 @@
/* These functions only work properly if p is an (unsigned char *) */
#define WRITE_BYTE(ptr, val) \
#define WRITE_8(ptr, val) \
*((ptr)++) = (unsigned char)((val) & 0xFF)
#define WRITE_SHORT(ptr, val) \
#define WRITE_16_L(ptr, val) \
do { \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
} while (0)
#define WRITE_LONG(ptr, val) \
#define WRITE_32_L(ptr, val) \
do { \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
@ -50,18 +50,33 @@
*((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
} while (0)
#define WRITE_16_B(ptr, val) \
do { \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
} while (0)
#define WRITE_32_B(ptr, val) \
do { \
*((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 16) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
} while (0)
/* Non-incrementing versions of the above. */
#define SAVE_BYTE(ptr, val) \
#define SAVE_8(ptr, val) \
*(ptr) = (unsigned char)((val) & 0xFF)
#define SAVE_SHORT(ptr, val) \
#define SAVE_16_L(ptr, val) \
do { \
*(ptr) = (unsigned char)((val) & 0xFF); \
*((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
} while (0)
#define SAVE_LONG(ptr, val) \
#define SAVE_32_L(ptr, val) \
do { \
*(ptr) = (unsigned char)((val) & 0xFF); \
*((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
@ -69,27 +84,43 @@
*((ptr)+3) = (unsigned char)(((val) >> 24) & 0xFF); \
} while (0)
#define SAVE_16_B(ptr, val) \
do { \
*(ptr) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)+1) = (unsigned char)((val) & 0xFF); \
} while (0)
#define SAVE_32_B(ptr, val) \
do { \
*(ptr) = (unsigned char)(((val) >> 24) & 0xFF); \
*((ptr)+1) = (unsigned char)(((val) >> 16) & 0xFF); \
*((ptr)+2) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)+3) = (unsigned char)((val) & 0xFF); \
} while (0)
/* Direct-to-file versions of the above. Using the above macros and a single
* fwrite() will probably be faster than calling these functions many times.
* These functions return 1 if the write was successful, 0 if not (so their
* return values can be used like the return value from fwrite()).
*/
size_t fwrite_short(unsigned short val, FILE *f);
size_t fwrite_long(unsigned long val, FILE *f);
size_t fwrite_16_l(unsigned short val, FILE *f);
size_t fwrite_32_l(unsigned long val, FILE *f);
size_t fwrite_16_b(unsigned short val, FILE *f);
size_t fwrite_32_b(unsigned long val, FILE *f);
/* Read/Load versions. val is the variable to receive the data. */
#define READ_BYTE(val, ptr) \
#define READ_8(val, ptr) \
(val) = *((ptr)++) & 0xFF
#define READ_SHORT(val, ptr) \
#define READ_16_L(val, ptr) \
do { \
(val) = *((ptr)++) & 0xFF; \
(val) |= (*((ptr)++) & 0xFF) << 8; \
} while (0)
#define READ_LONG(val, ptr) \
#define READ_32_L(val, ptr) \
do { \
(val) = *((ptr)++) & 0xFF; \
(val) |= (*((ptr)++) & 0xFF) << 8; \
@ -97,18 +128,32 @@ size_t fwrite_long(unsigned long val, FILE *f);
(val) |= (*((ptr)++) & 0xFF) << 24; \
} while (0)
#define READ_16_B(val, ptr) \
do { \
(val) = (*((ptr)++) & 0xFF) << 8; \
(val) |= *((ptr)++) & 0xFF; \
} while (0)
#define READ_32_B(val, ptr) \
do { \
(val) = (*((ptr)++) & 0xFF) << 24; \
(val) |= (*((ptr)++) & 0xFF) << 16; \
(val) |= (*((ptr)++) & 0xFF) << 8; \
(val) |= *((ptr)++) & 0xFF; \
} while (0)
/* Non-incrementing versions of the above. */
#define LOAD_BYTE(val, ptr) \
#define LOAD_8(val, ptr) \
(val) = *(ptr) & 0xFF
#define LOAD_SHORT(val, ptr) \
#define LOAD_16_L(val, ptr) \
do { \
(val) = *(ptr) & 0xFF; \
(val) |= (*((ptr)+1) & 0xFF) << 8; \
} while (0)
#define LOAD_LONG(val, ptr) \
#define LOAD_32_L(val, ptr) \
do { \
(val) = (unsigned long)(*(ptr) & 0xFF); \
(val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 8); \
@ -116,4 +161,18 @@ size_t fwrite_long(unsigned long val, FILE *f);
(val) |= (unsigned long)((*((ptr)+3) & 0xFF) << 24); \
} while (0)
#define LOAD_16_B(val, ptr) \
do { \
(val) = (*(ptr) & 0xFF) << 8; \
(val) |= *((ptr)+1) & 0xFF; \
} while (0)
#define LOAD_32_B(val, ptr) \
do { \
(val) = (unsigned long)((*(ptr) & 0xFF) << 24); \
(val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 16); \
(val) |= (unsigned long)((*((ptr)+2) & 0xFF) << 8); \
(val) |= (unsigned long)(*((ptr)+3) & 0xFF); \
} while (0)
#endif

@ -529,7 +529,7 @@ floatnum_get_int(const floatnum *flt, unsigned long *ret_val)
return 1;
}
LOAD_LONG(*ret_val, &t[0]);
LOAD_32_L(*ret_val, &t[0]);
return 0;
}

@ -551,7 +551,7 @@ intnum_get_sized(const intnum *intn, unsigned char *ptr, size_t size)
case INTNUM_UL:
ul = intn->val.ul;
while (size-- > 0) {
WRITE_BYTE(ptr, ul);
WRITE_8(ptr, ul);
if (ul != 0)
ul >>= 8;
}

@ -22,9 +22,12 @@
#include "util.h"
/*@unused@*/ RCSID("$IdPath$");
#include "file.h"
#include "globals.h"
#include "errwarn.h"
#include "intnum.h"
#include "floatnum.h"
#include "expr.h"
#include "bytecode.h"
@ -177,6 +180,8 @@ arch x86_arch = {
x86_bc_resolve,
x86_bc_tobytes
},
x86_floatnum_tobytes,
x86_intnum_tobytes,
x86_get_reg_size,
x86_reg_print,
x86_segreg_print,

@ -220,6 +220,12 @@ void x86_handle_seg_prefix(bytecode *bc, unsigned long segreg);
void x86_handle_seg_override(effaddr *ea, unsigned long segreg);
int x86_floatnum_tobytes(const floatnum *flt, unsigned char **bufp,
unsigned long valsize, const expr *e);
int x86_intnum_tobytes(const intnum *intn, unsigned char **bufp,
unsigned long valsize, const expr *e,
const bytecode *bc, int rel);
unsigned int x86_get_reg_size(unsigned long reg);
void x86_reg_print(FILE *f, unsigned long reg);

@ -726,17 +726,17 @@ x86_bc_tobytes_insn(x86_insn *insn, unsigned char **bufp, const section *sect,
/* Prefixes */
if (insn->lockrep_pre != 0)
WRITE_BYTE(*bufp, insn->lockrep_pre);
WRITE_8(*bufp, insn->lockrep_pre);
if (ea && ead->segment != 0)
WRITE_BYTE(*bufp, ead->segment);
WRITE_8(*bufp, ead->segment);
if (insn->opersize != 0 && insn->opersize != insn->mode_bits)
WRITE_BYTE(*bufp, 0x66);
WRITE_8(*bufp, 0x66);
if (insn->addrsize != 0 && insn->addrsize != insn->mode_bits)
WRITE_BYTE(*bufp, 0x67);
WRITE_8(*bufp, 0x67);
/* Opcode */
for (i=0; i<insn->opcode_len; i++)
WRITE_BYTE(*bufp, insn->opcode[i]);
WRITE_8(*bufp, insn->opcode[i]);
/* Effective address: ModR/M (if required), SIB (if required), and
* displacement (if required).
@ -745,13 +745,13 @@ x86_bc_tobytes_insn(x86_insn *insn, unsigned char **bufp, const section *sect,
if (ead->need_modrm) {
if (!ead->valid_modrm)
InternalError(_("invalid Mod/RM in x86 tobytes_insn"));
WRITE_BYTE(*bufp, ead->modrm);
WRITE_8(*bufp, ead->modrm);
}
if (ead->need_sib) {
if (!ead->valid_sib)
InternalError(_("invalid SIB in x86 tobytes_insn"));
WRITE_BYTE(*bufp, ead->sib);
WRITE_8(*bufp, ead->sib);
}
if (ea->disp) {
@ -780,7 +780,7 @@ x86_bc_tobytes_insn(x86_insn *insn, unsigned char **bufp, const section *sect,
* write out 0 value.
*/
for (i=0; i<ea->len; i++)
WRITE_BYTE(*bufp, 0);
WRITE_8(*bufp, 0);
}
}
}
@ -805,12 +805,12 @@ x86_bc_tobytes_jmprel(x86_jmprel *jmprel, unsigned char **bufp,
/* Prefixes */
if (jmprel->lockrep_pre != 0)
WRITE_BYTE(*bufp, jmprel->lockrep_pre);
WRITE_8(*bufp, jmprel->lockrep_pre);
/* FIXME: branch hints! */
if (jmprel->opersize != 0 && jmprel->opersize != jmprel->mode_bits)
WRITE_BYTE(*bufp, 0x66);
WRITE_8(*bufp, 0x66);
if (jmprel->addrsize != 0 && jmprel->addrsize != jmprel->mode_bits)
WRITE_BYTE(*bufp, 0x67);
WRITE_8(*bufp, 0x67);
/* As opersize may be 0, figure out its "real" value. */
opersize = (jmprel->opersize == 0) ? jmprel->mode_bits :
@ -826,7 +826,7 @@ x86_bc_tobytes_jmprel(x86_jmprel *jmprel, unsigned char **bufp,
/* Opcode */
for (i=0; i<jmprel->shortop.opcode_len; i++)
WRITE_BYTE(*bufp, jmprel->shortop.opcode[i]);
WRITE_8(*bufp, jmprel->shortop.opcode[i]);
/* Relative displacement */
if (output_expr(&jmprel->target, bufp, 1, sect, bc, 1, d))
@ -842,7 +842,7 @@ x86_bc_tobytes_jmprel(x86_jmprel *jmprel, unsigned char **bufp,
/* Opcode */
for (i=0; i<jmprel->nearop.opcode_len; i++)
WRITE_BYTE(*bufp, jmprel->nearop.opcode[i]);
WRITE_8(*bufp, jmprel->nearop.opcode[i]);
/* Relative displacement */
if (output_expr(&jmprel->target, bufp,
@ -876,3 +876,32 @@ x86_bc_tobytes(bytecode *bc, unsigned char **bufp, const section *sect,
return 0;
}
int
x86_intnum_tobytes(const intnum *intn, unsigned char **bufp,
unsigned long valsize, const expr *e, const bytecode *bc,
int rel)
{
if (rel) {
long val;
if (valsize != 1 && valsize != 2 && valsize != 4)
InternalError(_("tried to do PC-relative offset from invalid sized value"));
val = intnum_get_uint(intn);
val -= bc->len;
switch (valsize) {
case 1:
WRITE_8(*bufp, val);
break;
case 2:
WRITE_16_L(*bufp, val);
break;
case 4:
WRITE_32_L(*bufp, val);
break;
}
} else {
/* Write value out. */
intnum_get_sized(intn, *bufp, (size_t)valsize);
*bufp += valsize;
}
return 0;
}

@ -771,3 +771,27 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
}
return 1;
}
int
x86_floatnum_tobytes(const floatnum *flt, unsigned char **bufp,
unsigned long valsize, const expr *e)
{
int fltret;
if (!floatnum_check_size(flt, (size_t)valsize)) {
ErrorAt(e->line, _("invalid floating point constant size"));
return 1;
}
fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize);
if (fltret < 0) {
ErrorAt(e->line, _("underflow in floating point expression"));
return 1;
}
if (fltret > 0) {
ErrorAt(e->line, _("overflow in floating point expression"));
return 1;
}
*bufp += valsize;
return 0;
}

@ -37,6 +37,7 @@
#include "expr-int.h"
#include "bc-int.h"
#include "arch.h"
#include "objfmt.h"
@ -106,7 +107,7 @@ bin_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize,
/*@observer@*/ const bytecode *bc, int rel,
/*@unused@*/ /*@null@*/ void *d)
{
/*@dependent@*/ /*@null@*/ const intnum *num;
/*@dependent@*/ /*@null@*/ const intnum *intn;
/*@dependent@*/ /*@null@*/ const floatnum *flt;
assert(info != NULL);
@ -120,54 +121,13 @@ bin_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize,
/* Handle floating point expressions */
flt = expr_get_floatnum(ep);
if (flt) {
int fltret;
if (!floatnum_check_size(flt, (size_t)valsize)) {
ErrorAt((*ep)->line, _("invalid floating point constant size"));
return 1;
}
fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize);
if (fltret < 0) {
ErrorAt((*ep)->line, _("underflow in floating point expression"));
return 1;
}
if (fltret > 0) {
ErrorAt((*ep)->line, _("overflow in floating point expression"));
return 1;
}
*bufp += valsize;
return 0;
}
if (flt)
return cur_arch->floatnum_tobytes(flt, bufp, valsize, *ep);
/* Handle integer expressions */
num = expr_get_intnum(ep, NULL);
if (num) {
if (rel) {
long val;
if (valsize != 1 && valsize != 2 && valsize != 4)
InternalError(_("tried to do PC-relative offset from invalid sized value"));
val = intnum_get_uint(num);
val -= bc->len;
switch (valsize) {
case 1:
WRITE_BYTE(*bufp, val);
break;
case 2:
WRITE_SHORT(*bufp, val);
break;
case 4:
WRITE_LONG(*bufp, val);
break;
}
} else {
/* Write value out. */
intnum_get_sized(num, *bufp, (size_t)valsize);
*bufp += valsize;
}
return 0;
}
intn = expr_get_intnum(ep, NULL);
if (intn)
return cur_arch->intnum_tobytes(intn, bufp, valsize, *ep, bc, rel);
/* Check for complex float expressions */
if (expr_contains(*ep, EXPR_FLOAT)) {

@ -141,6 +141,17 @@ struct arch {
output_expr_func output_expr);
} bc;
/* Functions to output floats and integers, architecture-specific because
* of endianness. Returns nonzero on error, otherwise updates bufp by
* valsize (bytes saved to bufp). For intnums, rel indicates a relative
* displacement, and bc is the containing bytecode to compute it from.
*/
int (*floatnum_tobytes) (const floatnum *flt, unsigned char **bufp,
unsigned long valsize, const expr *e);
int (*intnum_tobytes) (const intnum *intn, unsigned char **bufp,
unsigned long valsize, const expr *e,
const bytecode *bc, int rel);
/* Gets the equivalent register size in bytes. Returns 0 if there is no
* suitable equivalent size.
*/

@ -22,9 +22,12 @@
#include "util.h"
/*@unused@*/ RCSID("$IdPath$");
#include "file.h"
#include "globals.h"
#include "errwarn.h"
#include "intnum.h"
#include "floatnum.h"
#include "expr.h"
#include "bytecode.h"
@ -177,6 +180,8 @@ arch x86_arch = {
x86_bc_resolve,
x86_bc_tobytes
},
x86_floatnum_tobytes,
x86_intnum_tobytes,
x86_get_reg_size,
x86_reg_print,
x86_segreg_print,

@ -220,6 +220,12 @@ void x86_handle_seg_prefix(bytecode *bc, unsigned long segreg);
void x86_handle_seg_override(effaddr *ea, unsigned long segreg);
int x86_floatnum_tobytes(const floatnum *flt, unsigned char **bufp,
unsigned long valsize, const expr *e);
int x86_intnum_tobytes(const intnum *intn, unsigned char **bufp,
unsigned long valsize, const expr *e,
const bytecode *bc, int rel);
unsigned int x86_get_reg_size(unsigned long reg);
void x86_reg_print(FILE *f, unsigned long reg);

@ -726,17 +726,17 @@ x86_bc_tobytes_insn(x86_insn *insn, unsigned char **bufp, const section *sect,
/* Prefixes */
if (insn->lockrep_pre != 0)
WRITE_BYTE(*bufp, insn->lockrep_pre);
WRITE_8(*bufp, insn->lockrep_pre);
if (ea && ead->segment != 0)
WRITE_BYTE(*bufp, ead->segment);
WRITE_8(*bufp, ead->segment);
if (insn->opersize != 0 && insn->opersize != insn->mode_bits)
WRITE_BYTE(*bufp, 0x66);
WRITE_8(*bufp, 0x66);
if (insn->addrsize != 0 && insn->addrsize != insn->mode_bits)
WRITE_BYTE(*bufp, 0x67);
WRITE_8(*bufp, 0x67);
/* Opcode */
for (i=0; i<insn->opcode_len; i++)
WRITE_BYTE(*bufp, insn->opcode[i]);
WRITE_8(*bufp, insn->opcode[i]);
/* Effective address: ModR/M (if required), SIB (if required), and
* displacement (if required).
@ -745,13 +745,13 @@ x86_bc_tobytes_insn(x86_insn *insn, unsigned char **bufp, const section *sect,
if (ead->need_modrm) {
if (!ead->valid_modrm)
InternalError(_("invalid Mod/RM in x86 tobytes_insn"));
WRITE_BYTE(*bufp, ead->modrm);
WRITE_8(*bufp, ead->modrm);
}
if (ead->need_sib) {
if (!ead->valid_sib)
InternalError(_("invalid SIB in x86 tobytes_insn"));
WRITE_BYTE(*bufp, ead->sib);
WRITE_8(*bufp, ead->sib);
}
if (ea->disp) {
@ -780,7 +780,7 @@ x86_bc_tobytes_insn(x86_insn *insn, unsigned char **bufp, const section *sect,
* write out 0 value.
*/
for (i=0; i<ea->len; i++)
WRITE_BYTE(*bufp, 0);
WRITE_8(*bufp, 0);
}
}
}
@ -805,12 +805,12 @@ x86_bc_tobytes_jmprel(x86_jmprel *jmprel, unsigned char **bufp,
/* Prefixes */
if (jmprel->lockrep_pre != 0)
WRITE_BYTE(*bufp, jmprel->lockrep_pre);
WRITE_8(*bufp, jmprel->lockrep_pre);
/* FIXME: branch hints! */
if (jmprel->opersize != 0 && jmprel->opersize != jmprel->mode_bits)
WRITE_BYTE(*bufp, 0x66);
WRITE_8(*bufp, 0x66);
if (jmprel->addrsize != 0 && jmprel->addrsize != jmprel->mode_bits)
WRITE_BYTE(*bufp, 0x67);
WRITE_8(*bufp, 0x67);
/* As opersize may be 0, figure out its "real" value. */
opersize = (jmprel->opersize == 0) ? jmprel->mode_bits :
@ -826,7 +826,7 @@ x86_bc_tobytes_jmprel(x86_jmprel *jmprel, unsigned char **bufp,
/* Opcode */
for (i=0; i<jmprel->shortop.opcode_len; i++)
WRITE_BYTE(*bufp, jmprel->shortop.opcode[i]);
WRITE_8(*bufp, jmprel->shortop.opcode[i]);
/* Relative displacement */
if (output_expr(&jmprel->target, bufp, 1, sect, bc, 1, d))
@ -842,7 +842,7 @@ x86_bc_tobytes_jmprel(x86_jmprel *jmprel, unsigned char **bufp,
/* Opcode */
for (i=0; i<jmprel->nearop.opcode_len; i++)
WRITE_BYTE(*bufp, jmprel->nearop.opcode[i]);
WRITE_8(*bufp, jmprel->nearop.opcode[i]);
/* Relative displacement */
if (output_expr(&jmprel->target, bufp,
@ -876,3 +876,32 @@ x86_bc_tobytes(bytecode *bc, unsigned char **bufp, const section *sect,
return 0;
}
int
x86_intnum_tobytes(const intnum *intn, unsigned char **bufp,
unsigned long valsize, const expr *e, const bytecode *bc,
int rel)
{
if (rel) {
long val;
if (valsize != 1 && valsize != 2 && valsize != 4)
InternalError(_("tried to do PC-relative offset from invalid sized value"));
val = intnum_get_uint(intn);
val -= bc->len;
switch (valsize) {
case 1:
WRITE_8(*bufp, val);
break;
case 2:
WRITE_16_L(*bufp, val);
break;
case 4:
WRITE_32_L(*bufp, val);
break;
}
} else {
/* Write value out. */
intnum_get_sized(intn, *bufp, (size_t)valsize);
*bufp += valsize;
}
return 0;
}

@ -771,3 +771,27 @@ x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
}
return 1;
}
int
x86_floatnum_tobytes(const floatnum *flt, unsigned char **bufp,
unsigned long valsize, const expr *e)
{
int fltret;
if (!floatnum_check_size(flt, (size_t)valsize)) {
ErrorAt(e->line, _("invalid floating point constant size"));
return 1;
}
fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize);
if (fltret < 0) {
ErrorAt(e->line, _("underflow in floating point expression"));
return 1;
}
if (fltret > 0) {
ErrorAt(e->line, _("overflow in floating point expression"));
return 1;
}
*bufp += valsize;
return 0;
}

@ -668,7 +668,7 @@ bc_tobytes_data(bytecode_data *bc_data, unsigned char **bufp,
if (slen > 0) {
slen = bc_data->size-slen;
for (i=0; i<slen; i++)
WRITE_BYTE(*bufp, 0);
WRITE_8(*bufp, 0);
}
break;
}

@ -75,7 +75,7 @@ replace_extension(const char *orig, /*@null@*/ const char *ext,
}
size_t
fwrite_short(unsigned short val, FILE *f)
fwrite_16_l(unsigned short val, FILE *f)
{
if (fputc(val & 0xFF, f) == EOF)
return 0;
@ -85,7 +85,7 @@ fwrite_short(unsigned short val, FILE *f)
}
size_t
fwrite_long(unsigned long val, FILE *f)
fwrite_32_l(unsigned long val, FILE *f)
{
if (fputc((int)(val & 0xFF), f) == EOF)
return 0;
@ -97,3 +97,27 @@ fwrite_long(unsigned long val, FILE *f)
return 0;
return 1;
}
size_t
fwrite_16_b(unsigned short val, FILE *f)
{
if (fputc((val >> 8) & 0xFF, f) == EOF)
return 0;
if (fputc(val & 0xFF, f) == EOF)
return 0;
return 1;
}
size_t
fwrite_32_b(unsigned long val, FILE *f)
{
if (fputc((int)((val >> 24) & 0xFF), f) == EOF)
return 0;
if (fputc((int)((val >> 16) & 0xFF), f) == EOF)
return 0;
if (fputc((int)((val >> 8) & 0xFF), f) == EOF)
return 0;
if (fputc((int)(val & 0xFF), f) == EOF)
return 0;
return 1;
}

@ -1,5 +1,5 @@
/* $IdPath$
* Little-endian file functions header file.
* Big and little endian file functions header file.
*
* Copyright (C) 2001 Peter Johnson
*
@ -33,16 +33,16 @@
/* These functions only work properly if p is an (unsigned char *) */
#define WRITE_BYTE(ptr, val) \
#define WRITE_8(ptr, val) \
*((ptr)++) = (unsigned char)((val) & 0xFF)
#define WRITE_SHORT(ptr, val) \
#define WRITE_16_L(ptr, val) \
do { \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
} while (0)
#define WRITE_LONG(ptr, val) \
#define WRITE_32_L(ptr, val) \
do { \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
@ -50,18 +50,33 @@
*((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
} while (0)
#define WRITE_16_B(ptr, val) \
do { \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
} while (0)
#define WRITE_32_B(ptr, val) \
do { \
*((ptr)++) = (unsigned char)(((val) >> 24) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 16) & 0xFF); \
*((ptr)++) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)++) = (unsigned char)((val) & 0xFF); \
} while (0)
/* Non-incrementing versions of the above. */
#define SAVE_BYTE(ptr, val) \
#define SAVE_8(ptr, val) \
*(ptr) = (unsigned char)((val) & 0xFF)
#define SAVE_SHORT(ptr, val) \
#define SAVE_16_L(ptr, val) \
do { \
*(ptr) = (unsigned char)((val) & 0xFF); \
*((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
} while (0)
#define SAVE_LONG(ptr, val) \
#define SAVE_32_L(ptr, val) \
do { \
*(ptr) = (unsigned char)((val) & 0xFF); \
*((ptr)+1) = (unsigned char)(((val) >> 8) & 0xFF); \
@ -69,27 +84,43 @@
*((ptr)+3) = (unsigned char)(((val) >> 24) & 0xFF); \
} while (0)
#define SAVE_16_B(ptr, val) \
do { \
*(ptr) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)+1) = (unsigned char)((val) & 0xFF); \
} while (0)
#define SAVE_32_B(ptr, val) \
do { \
*(ptr) = (unsigned char)(((val) >> 24) & 0xFF); \
*((ptr)+1) = (unsigned char)(((val) >> 16) & 0xFF); \
*((ptr)+2) = (unsigned char)(((val) >> 8) & 0xFF); \
*((ptr)+3) = (unsigned char)((val) & 0xFF); \
} while (0)
/* Direct-to-file versions of the above. Using the above macros and a single
* fwrite() will probably be faster than calling these functions many times.
* These functions return 1 if the write was successful, 0 if not (so their
* return values can be used like the return value from fwrite()).
*/
size_t fwrite_short(unsigned short val, FILE *f);
size_t fwrite_long(unsigned long val, FILE *f);
size_t fwrite_16_l(unsigned short val, FILE *f);
size_t fwrite_32_l(unsigned long val, FILE *f);
size_t fwrite_16_b(unsigned short val, FILE *f);
size_t fwrite_32_b(unsigned long val, FILE *f);
/* Read/Load versions. val is the variable to receive the data. */
#define READ_BYTE(val, ptr) \
#define READ_8(val, ptr) \
(val) = *((ptr)++) & 0xFF
#define READ_SHORT(val, ptr) \
#define READ_16_L(val, ptr) \
do { \
(val) = *((ptr)++) & 0xFF; \
(val) |= (*((ptr)++) & 0xFF) << 8; \
} while (0)
#define READ_LONG(val, ptr) \
#define READ_32_L(val, ptr) \
do { \
(val) = *((ptr)++) & 0xFF; \
(val) |= (*((ptr)++) & 0xFF) << 8; \
@ -97,18 +128,32 @@ size_t fwrite_long(unsigned long val, FILE *f);
(val) |= (*((ptr)++) & 0xFF) << 24; \
} while (0)
#define READ_16_B(val, ptr) \
do { \
(val) = (*((ptr)++) & 0xFF) << 8; \
(val) |= *((ptr)++) & 0xFF; \
} while (0)
#define READ_32_B(val, ptr) \
do { \
(val) = (*((ptr)++) & 0xFF) << 24; \
(val) |= (*((ptr)++) & 0xFF) << 16; \
(val) |= (*((ptr)++) & 0xFF) << 8; \
(val) |= *((ptr)++) & 0xFF; \
} while (0)
/* Non-incrementing versions of the above. */
#define LOAD_BYTE(val, ptr) \
#define LOAD_8(val, ptr) \
(val) = *(ptr) & 0xFF
#define LOAD_SHORT(val, ptr) \
#define LOAD_16_L(val, ptr) \
do { \
(val) = *(ptr) & 0xFF; \
(val) |= (*((ptr)+1) & 0xFF) << 8; \
} while (0)
#define LOAD_LONG(val, ptr) \
#define LOAD_32_L(val, ptr) \
do { \
(val) = (unsigned long)(*(ptr) & 0xFF); \
(val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 8); \
@ -116,4 +161,18 @@ size_t fwrite_long(unsigned long val, FILE *f);
(val) |= (unsigned long)((*((ptr)+3) & 0xFF) << 24); \
} while (0)
#define LOAD_16_B(val, ptr) \
do { \
(val) = (*(ptr) & 0xFF) << 8; \
(val) |= *((ptr)+1) & 0xFF; \
} while (0)
#define LOAD_32_B(val, ptr) \
do { \
(val) = (unsigned long)((*(ptr) & 0xFF) << 24); \
(val) |= (unsigned long)((*((ptr)+1) & 0xFF) << 16); \
(val) |= (unsigned long)((*((ptr)+2) & 0xFF) << 8); \
(val) |= (unsigned long)(*((ptr)+3) & 0xFF); \
} while (0)
#endif

@ -529,7 +529,7 @@ floatnum_get_int(const floatnum *flt, unsigned long *ret_val)
return 1;
}
LOAD_LONG(*ret_val, &t[0]);
LOAD_32_L(*ret_val, &t[0]);
return 0;
}

@ -551,7 +551,7 @@ intnum_get_sized(const intnum *intn, unsigned char *ptr, size_t size)
case INTNUM_UL:
ul = intn->val.ul;
while (size-- > 0) {
WRITE_BYTE(ptr, ul);
WRITE_8(ptr, ul);
if (ul != 0)
ul >>= 8;
}

@ -37,6 +37,7 @@
#include "expr-int.h"
#include "bc-int.h"
#include "arch.h"
#include "objfmt.h"
@ -106,7 +107,7 @@ bin_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize,
/*@observer@*/ const bytecode *bc, int rel,
/*@unused@*/ /*@null@*/ void *d)
{
/*@dependent@*/ /*@null@*/ const intnum *num;
/*@dependent@*/ /*@null@*/ const intnum *intn;
/*@dependent@*/ /*@null@*/ const floatnum *flt;
assert(info != NULL);
@ -120,54 +121,13 @@ bin_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize,
/* Handle floating point expressions */
flt = expr_get_floatnum(ep);
if (flt) {
int fltret;
if (!floatnum_check_size(flt, (size_t)valsize)) {
ErrorAt((*ep)->line, _("invalid floating point constant size"));
return 1;
}
fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize);
if (fltret < 0) {
ErrorAt((*ep)->line, _("underflow in floating point expression"));
return 1;
}
if (fltret > 0) {
ErrorAt((*ep)->line, _("overflow in floating point expression"));
return 1;
}
*bufp += valsize;
return 0;
}
if (flt)
return cur_arch->floatnum_tobytes(flt, bufp, valsize, *ep);
/* Handle integer expressions */
num = expr_get_intnum(ep, NULL);
if (num) {
if (rel) {
long val;
if (valsize != 1 && valsize != 2 && valsize != 4)
InternalError(_("tried to do PC-relative offset from invalid sized value"));
val = intnum_get_uint(num);
val -= bc->len;
switch (valsize) {
case 1:
WRITE_BYTE(*bufp, val);
break;
case 2:
WRITE_SHORT(*bufp, val);
break;
case 4:
WRITE_LONG(*bufp, val);
break;
}
} else {
/* Write value out. */
intnum_get_sized(num, *bufp, (size_t)valsize);
*bufp += valsize;
}
return 0;
}
intn = expr_get_intnum(ep, NULL);
if (intn)
return cur_arch->intnum_tobytes(intn, bufp, valsize, *ep, bc, rel);
/* Check for complex float expressions */
if (expr_contains(*ep, EXPR_FLOAT)) {

Loading…
Cancel
Save