X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=mark.c;h=7378c8a6916aee2d8804c39901c042e39908e93b;hp=d593b21d6997adda8fbf45015fb0672bd48e586d;hb=582df8950c285e1746d0c4a9e3ead6545c962dc8;hpb=d1fe92e22362ab81cdf10f09b4847261f3b9899a diff --git a/mark.c b/mark.c index d593b21..7378c8a 100644 --- a/mark.c +++ b/mark.c @@ -1,7 +1,7 @@ // -// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System +// RMAC - Reboot's Macro Assembler for all Atari computers // MARK.C - A record of things that are defined relative to any of the sections -// Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends +// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 // Source utilised with the kind permission of Landon Dyer // @@ -10,19 +10,26 @@ #include "error.h" #include "object.h" #include "riscasm.h" +#include "sect.h" +#define MARK_ALLOC_INCR 1024 // # bytes to alloc for more mark space +#define MIN_MARK_MEM (3 * sizeof(uint16_t) + 1 * sizeof(uint32_t) + sizeof(SYM *)) + MCHUNK * firstmch; // First mark chunk MCHUNK * curmch; // Current mark chunk PTR markptr; // Deposit point in current mark chunk -LONG mcalloc; // #bytes alloc'd to current mark chunk -LONG mcused; // #bytes used in current mark chunk +uint32_t mcalloc; // # bytes alloc'd to current mark chunk +uint32_t mcused; // # bytes used in current mark chunk uint16_t curfrom; // Current "from" section -// -// Imports -// -extern int prg_flag; // 1, write ".PRG" relocatable executable +// Table to convert from TDB to fixup triad +static uint8_t mark_tr[] = { + 0, // (N/A) + 2, // TEXT relocatable + 1, 0, // DATA relocatable + 3 // BSS relocatable +}; //#define DEBUG_IMAGE_MARKING @@ -35,6 +42,7 @@ void InitMark(void) firstmch = curmch = NULL; mcalloc = mcused = 0; curfrom = 0; + sect[TEXT].relocs = sect[DATA].relocs = sect[BSS].relocs = 0; } @@ -46,57 +54,62 @@ void StopMark(void) if (curmch) { *markptr.wp = MCHEND; // Mark end of block - curmch->mcused = mcused; // Update #used in mark block + curmch->mcused = mcused; // Update # used in mark block } } // -// Mark a word or longword relocatable +// Mark a word or longword as relocatable // -int rmark(uint16_t from, uint32_t loc, uint16_t to, uint16_t size, SYM * symbol) +// Record is either 2, 3, or 4 pieces of data long. A mark is of the form: +// .W section mark is relative to, and flags in upper byte +// .L location of mark in "from" section +// .W [from] new from section (if different from current) +// .L [symbol] symbol involved in external reference (if any) +// +uint32_t MarkRelocatable(uint16_t section, uint32_t loc, uint16_t to, uint16_t flags, SYM * symbol) { #ifdef DEBUG_IMAGE_MARKING -printf("rmark: from=%i, loc=$%X, to=$%X, size=$%x, symbol=$%X\n", from, loc, to, size, symbol); +printf("MarkRelocatable: section=%i, loc=$%X, to=$%X, flags=$%x, symbol=$%X\n", section, loc, to, flags, symbol); if (symbol) printf(" symbol->stype=$%02X, sattr=$%04X, sattre=$%08X, svalue=%i, sname=%s\n", symbol->stype, symbol->sattr, symbol->sattre, symbol->svalue, symbol->sname); #endif if ((mcalloc - mcused) < MIN_MARK_MEM) - amark(); + AllocateMark(); - uint16_t flags = (size | to); + // Set up flags + flags |= to; - if (from != curfrom) + if (section != curfrom) flags |= MCHFROM; if (symbol != NULL) flags |= MSYMBOL; // - // Complain about some things are not allowed in `-p' mode: - // o marks that aren't to LONGs; - // o external references. + // Complain about some things are not allowed in '-p' (PRG) mode: + // o Marks that aren't to LONGs + // o External references // if (prg_flag) { - if ((flags & MLONG) == 0) - error("illegal word relocatable (in .PRG mode)"); - if (symbol != NULL) - errors("illegal external reference (in .PRG mode) to '%s'", - symbol->sname); + error("illegal external reference (in .PRG mode) to '%s'", + symbol->sname); } - mcused += sizeof(WORD) + sizeof(LONG); + // Dump crap into the mark *markptr.wp++ = flags; *markptr.lp++ = loc; + mcused += sizeof(uint16_t) + sizeof(uint32_t); if (flags & MCHFROM) { - curfrom = from; - *markptr.wp++ = from; - mcused += sizeof(WORD); + curfrom = section; + *markptr.wp++ = section; + mcused += sizeof(uint16_t); } if (flags & MSYMBOL) @@ -105,6 +118,11 @@ if (symbol) mcused += sizeof(SYM *); } + // Increment # of relocs in this section + sect[section].relocs++; + + // Not sure what this is about (making sure the next mark is clear until + // it's marked as the end--I think)... *markptr.wp = 0x0000; return 0; @@ -114,29 +132,28 @@ if (symbol) // // Allocate another chunk of mark space // -int amark(void) +uint32_t AllocateMark(void) { -// MCHUNK * p; - // Alloc mark block header (and data) and set it up. -// p = (MCHUNK *)amem((long)(sizeof(MCHUNK)) + MARK_ALLOC_INCR); - MCHUNK * p = (MCHUNK *)malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR); + MCHUNK * p = malloc(sizeof(MCHUNK) + MARK_ALLOC_INCR); p->mcnext = NULL; p->mcalloc = MARK_ALLOC_INCR; - p->mcptr.cp = (char *)(((char *)p) + sizeof(MCHUNK)); + p->mcptr.cp = (uint8_t *)p + sizeof(MCHUNK); + p->mcused = 0; + + if (firstmch == NULL) + firstmch = p; if (curmch) { - // Link onto previous chunk - *markptr.wp++ = MCHEND; // Mark end of block + // Link onto previous chunk + *markptr.wp++ = MCHEND; // Mark end of block curmch->mcused = mcused; curmch->mcnext = p; } - if (!firstmch) - firstmch = p; - - curmch = p; // Setup global vars + // Setup global vars + curmch = p; markptr = p->mcptr; mcalloc = MARK_ALLOC_INCR; mcused = 0; @@ -145,73 +162,48 @@ int amark(void) } -/* - * Table to convert from TDB to fixup triad - * - */ -static char mark_tr[] = { - 0, /* (n/a) */ - 2, /* TEXT relocatable */ - 1, 0, /* DATA relocatable */ - 3 /* BSS relocatable */ -}; - - -/* - * Make mark image for Alcyon .o file - * okflag -- 1, ok to deposit reloc information - */ -LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) +// +// Make mark image for Alcyon .o file +// okflag: 1, ok to deposit reloc information +// +uint32_t MarkImage(register uint8_t * mp, uint32_t siz, uint32_t tsize, int okflag) { - MCHUNK * mch; /* -> mark chunk */ - register PTR p; /* source point from within mark chunk */ - WORD from; /* section fixups are currently FROM */ - register WORD w; /* a word (temp) */ - LONG loc; /* location (temp) */ - LONG lastloc; /* last location fixed up (RELMOD) */ - SYM * symbol; /* -> symbols (temp) */ - char * wp; /* pointer into raw relocation information */ - register char * dp; /* deposit point for RELMOD information */ - int firstp; /* 1, first relocation (RELMOD) */ - LONG diff; /* difference to relocate (RELMOD) */ + uint16_t from = 0; // Section fixups are currently FROM + uint32_t loc; // Location (temp) + uint32_t lastloc; // Last location fixed up (RELMOD) + uint8_t * wp; // Pointer into raw relocation information + register uint8_t * dp; // Deposit point for RELMOD information if (okflag) - //clear(mp, siz); /* zero relocation buffer */ - memset(mp, 0, siz); /* zero relocation buffer */ - - from = 0; + memset(mp, 0, siz); // zero relocation buffer - for(mch=firstmch; mch!=NULL; mch=mch->mcnext) + for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext) { - for(p=mch->mcptr;;) + for(PTR p=mch->mcptr;;) { - w = *p.wp++; /* w = next mark entry */ + uint16_t w = *p.wp++;// w = next mark entry - if (w & MCHEND) /* (end of mark chunk) */ + if (w & MCHEND) // (end of mark chunk) break; - /* - * Get mark record - */ - symbol = NULL; - loc = *p.lp++; /* mark location */ + // Get mark record + SYM * symbol = NULL; + loc = *p.lp++; // mark location - if (w & MCHFROM) /* maybe change "from" section */ + if (w & MCHFROM) // maybe change "from" section from = *p.wp++; - if (w & MSYMBOL) /* maybe includes a symbol */ + if (w & MSYMBOL) // maybe includes a symbol symbol = *p.sy++; - /* - * Compute mark position in relocation information; - * in RELMOD mode, get address of data to fix up. - */ + // Compute mark position in relocation information; in RELMOD mode, + // get address of data to fix up. if (from == DATA) loc += tsize; - wp = (char *)(mp + loc); + wp = (uint8_t *)(mp + loc); - if (okflag && (w & MLONG)) /* indicate first word of long */ + if (okflag && (w & MLONG)) // indicate first word of long { wp[1] = 5; wp += 2; @@ -219,15 +211,13 @@ LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) if (symbol) { - /* - * Deposit external reference - */ + // Deposit external reference if (okflag) { if (w & MPCREL) - w = 6; /* pc-relative fixup */ + w = 6; // PC-relative fixup else - w = 4; /* absolute fixup */ + w = 4; // Absolute fixup w |= symbol->senv << 3; *wp++ = w >> 8; @@ -236,27 +226,19 @@ LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) } else { - /* - * Deposit section-relative mark; - * in RELMOD mode, fix it up in the chunk, - * kind of like a sleazoid linker. - * - * In RELMOD mode, marks to words (MWORDs) "cannot happen," - * checks are made when mark() is called, so we don't have - * to check again here. - */ + // Deposit section-relative mark; in RELMOD mode, fix it up in + // the chunk, kind of like a sleazoid linker. + // + // In RELMOD mode, marks to words (MWORDs) "cannot happen," + // checks are made when mark() is called, so we don't have to + // check again here. w &= TDB; if (okflag) wp[1] = mark_tr[w]; else if (prg_flag && (w & (DATA | BSS))) { - dp = wp; - diff = ((LONG)(*dp++ & 0xff)) << 24; - diff |= ((LONG)(*dp++ & 0xff)) << 16; - diff |= ((LONG)(*dp++ & 0xff)) << 8; - diff |= (LONG)(*dp & 0xff); - + uint32_t diff = GETBE32(wp, 0); #ifdef DO_DEBUG DEBUG printf("diff=%lx ==> ", diff); #endif @@ -265,11 +247,7 @@ LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) if (w == BSS) diff += sect[DATA].sloc; - dp = wp; - *dp++ = (char)(diff >> 24); - *dp++ = (char)(diff >> 16); - *dp++ = (char)(diff >> 8); - *dp = (char)diff; + SETBE32(wp, 0, diff) #ifdef DO_DEBUG DEBUG printf("%lx\n", diff); #endif @@ -278,15 +256,12 @@ LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) } } - /* - * Generate ".PRG" relocation information in place in - * the relocation words (the ``RELMOD'' operation). - */ + // Generate ".PRG" relocation information in place in the relocation words + // (the "RELMOD" operation). if (okflag && prg_flag) { - firstp = 1; - wp = mp; - dp = mp; + int firstp = 1; + wp = dp = mp; for(loc=0; loc> 24); - *dp++ = (char)(loc >> 16); - *dp++ = (char)(loc >> 8); - *dp++ = (char)loc; + SETBE32(dp, 0, loc); + dp += 4; firstp = 0; } else { - for(diff=loc-lastloc; diff>254; diff-= 254) + uint32_t diff; + + for(diff=loc-lastloc; diff>254; diff-=254) *dp++ = 1; - *dp++ = (char)diff; + *dp++ = (uint8_t)diff; } - wp += 4; lastloc = loc; loc += 4; + wp += 4; } - else + else { loc += 2; wp += 2; } } - /* - * Terminate relocation list with 0L (if there was no - * relocation) or 0.B (if relocation information was - * written). - */ + // Terminate relocation list with 0L (if there was no relocation) or + // 0.B (if relocation information was written). if (!firstp) *dp++ = 0; - else for (firstp = 0; firstp < 4; ++firstp) - *dp++ = 0; + else + for(firstp=0; firstp<4; firstp++) + *dp++ = 0; - /* - * Return size of relocation information - */ + // Return size of relocation information loc = dp - mp; return loc; } @@ -343,211 +314,248 @@ LONG markimg(register char * mp, LONG siz, LONG tsize, int okflag) // // Make mark image for BSD .o file // -uint32_t bsdmarkimg(char * mp, LONG siz, LONG tsize, int reqseg) +// Assumptions about mark records (for BSD): if there is a symbol, the mark is +// for an undefined symbol, otherwise it's just a normal TDB relocation. +// N.B.: tsize is only used if reqseg is DATA +// +uint32_t MarkBSDImage(uint8_t * mp, uint32_t siz, uint32_t tsize, int reqseg) { - MCHUNK * mch; // Mark chunk - PTR p; // Source point from within mark chunk - uint16_t from; // Section fixups are currently FROM - uint16_t w; // A word (temp) - uint32_t loc; // Location (temp) - SYM * symbol; // Symbols (temp) - uint8_t * wp; // Pointer into raw relocation info - uint8_t * dp; // Deposit point for RELMOD info - uint32_t diff; // Difference to relocate (RELMOD) - uint32_t raddr, rflag = 0; // BSD relocation address and flags - uint32_t rsize; // Relocation size - int validsegment = 0; // Valid segment being processed + uint16_t from = 0; // Section fixups are currently FROM + uint32_t rsize = 0; // Relocation table size (written to mp) + int validsegment = 0; // We are not yet in a valid segment... #ifdef DEBUG_IMAGE_MARKING -printf("bsdmarkimg():\n"); +printf("MarkBSDImage():\n"); #endif - // Initialise relocation size - rsize = 0; + // Initialize relocation table point (for D_foo macros) chptr = mp; - from = 0; - for(mch=firstmch; mch!=NULL; mch=mch->mcnext) + // Run through all the relocation mark chunks + for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext) { - for(p=mch->mcptr;;) + for(PTR p=mch->mcptr;;) { - w = *p.wp++; // Next mark entry + SYM * symbol = NULL; + uint16_t w = *p.wp++; // Next mark entry + // If we hit the end of a chunk, go get the next one if (w & MCHEND) - break; // End of mark chunk + break; - // Get mark record - symbol = NULL; - loc = *p.lp++; // Mark location + // Get the rest of the mark record + uint32_t loc = *p.lp++; // Mark location + // Maybe change "from" section if (w & MCHFROM) { - // Maybe change "from" section from = *p.wp++; - if (obj_format == BSD) - { - if (reqseg == TEXT) - { - // Requested segment is TEXT - if (from == TEXT) - validsegment = 1; - else - validsegment = 0; - } - else - { - // Requested segment is DATA - if (from == DATA) - validsegment = 1; - else - validsegment = 0; - } - } + if (((reqseg == TEXT) && (from == TEXT)) + || ((reqseg == DATA) && (from == DATA))) + validsegment = 1; + else + validsegment = 0; } - if (w & MSYMBOL) // Maybe includes a symbol + // Maybe includes a symbol + if (w & MSYMBOL) symbol = *p.sy++; - if (obj_format == BSD) - { - raddr = loc; // Set relocation address + if (!validsegment) + continue; - if (validsegment) -#ifdef DEBUG_IMAGE_MARKING -{ -printf(" validsegment: raddr = $%08X\n", raddr); -#endif - D_long(raddr); // Write relocation address #ifdef DEBUG_IMAGE_MARKING -} +printf(" validsegment: raddr = $%08X\n", loc); #endif + uint32_t rflag = 0x00000040; // Absolute relocation - if (w & MPCREL) - rflag = 0x000000A0; // PC-relative fixup - else - rflag = 0x00000040; // Absolute fixup - -// This flag tells the linker to WORD swap the LONG when doing the fixup. - if (w & MMOVEI) -//{ -//printf("bsdmarkimg: ORing $01 to rflag (MMOVEI) [symbol=%s]...\n", symbol->sname); - rflag |= 0x00000001; -//} - } + if (w & MPCREL) + rflag = 0x000000A0; // PC-relative relocation - // Compute mark position in relocation information; - // in RELMOD mode, get address of data to fix up. - if (from == DATA) - loc += tsize; + // This flag tells the linker to WORD swap the LONG when doing the + // relocation. + if (w & MMOVEI) + rflag |= 0x00000001; - wp = (uint8_t *)(mp + loc); + // This tells the linker to do a WORD relocation (otherwise it + // defaults to doing a LONG, throwing things off for WORD sized + // fixups) + if (!(w & MLONG)) + rflag |= 0x00000002; - if (symbol) + if (symbol != NULL) { // Deposit external reference - if (obj_format == BSD) - { - rflag |= 0x00000010; // Set external reloc flag bit - rflag |= (symbol->senv << 8); // Put symbol index in flags + rflag |= 0x00000010; // Set external reloc flag bit + rflag |= (symbol->senv << 8); // Put symbol index in flags -// Looks like this is completely unnecessary (considering it does the wrong thing!) -#if 0 - if (symbol->sattre & RISCSYM) -{ -printf("bsdmarkimg: ORing $01 to rflag (RISCSYM) [symbol=%s]...\n", symbol->sname); - rflag |= 0x00000001; -} -#endif - - if (validsegment) - { #ifdef DEBUG_IMAGE_MARKING printf(" validsegment(2): rflag = $%08X\n", rflag); #endif - D_long(rflag); // Write relocation flags - rsize += 8; // Increment relocation size - } - } } else { - if (obj_format == BSD) - { #ifdef DEBUG_IMAGE_MARKING printf(" w = $%04X\n", w); #endif - w &= TDB; // Set reloc flags to segment + w &= TDB; // Set reloc flags to segment - switch (w) - { - case TEXT: rflag |= 0x00000400; break; - case DATA: rflag |= 0x00000600; break; - case BSS: rflag |= 0x00000800; break; - } + switch (w) + { + case TEXT: rflag |= 0x00000400; break; + case DATA: rflag |= 0x00000600; break; + case BSS: rflag |= 0x00000800; break; + } - if (validsegment) - { #ifdef DEBUG_IMAGE_MARKING printf(" validsegment(3): rflag = $%08X\n", rflag); #endif - D_long(rflag); // Write relocation flags - rsize += 8; // Increment relocation size - } + // Fix relocation by adding in start of TEXT segment, since it's + // currently relative to the start of the DATA (or BSS) segment + if (w & (DATA | BSS)) + { + uint8_t * dp = objImage + BSDHDRSIZE + loc; - w &= TDB; + // Bump the start of the section if it's DATA (& not TEXT) + if (from == DATA) + dp += tsize; - if (validsegment) - { - if (w & (DATA|BSS)) - { - dp = objImage + BSDHDRSIZE + loc; - diff = ((LONG)(*dp++ & 0xFF)) << 24; - diff |= ((LONG)(*dp++ & 0xFF)) << 16; - diff |= ((LONG)(*dp++ & 0xFF)) << 8; - diff |= (LONG)(*dp & 0xFF); - DEBUG printf("diff=%ux ==> ", diff); + uint32_t diff = (rflag & 0x02 ? GETBE16(dp, 0) : GETBE32(dp, 0)); + DEBUG printf("diff=%uX ==> ", diff); #ifdef DEBUG_IMAGE_MARKING printf(" validsegment(4): diff = $%08X --> ", diff); #endif - - if (rflag & 0x01) - diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000); + if (rflag & 0x01) + diff = WORDSWAP32(diff); - diff += sect[TEXT].sloc; + diff += sect[TEXT].sloc; + + if (w == BSS) + diff += sect[DATA].sloc; - if (w == BSS) - diff += sect[DATA].sloc; + if (rflag & 0x01) + diff = WORDSWAP32(diff); - if (rflag & 0x01) - diff = ((diff >> 16) & 0x0000FFFF) | ((diff << 16) & 0xFFFF0000); + // Make sure to deposit the correct size payload + // N.B.: The braces around the SETBExx macros are needed + // because the macro supplies its own set of braces, + // thus leaving a naked semicolon afterwards to + // screw up the if/else structure. This is the price + // you pay when using macros pretending to be code. + if (rflag & 0x02) + { + SETBE16(dp, 0, diff); + } + else + { + SETBE32(dp, 0, diff); + } - dp = objImage + BSDHDRSIZE + loc; - *dp++ = (char)(diff >> 24); - *dp++ = (char)(diff >> 16); - *dp++ = (char)(diff >> 8); - *dp = (char)diff; - DEBUG printf("%ux\n", diff); + DEBUG printf("%uX\n", diff); #ifdef DEBUG_IMAGE_MARKING printf("$%08X\n", diff); #endif - } - } } } + + D_long(loc); // Write relocation address + D_long(rflag); // Write relocation flags + rsize += 0x08; // Increment relocation size } } - // Return relocation size - if (obj_format == BSD) + // Return relocation table's size #ifdef DEBUG_IMAGE_MARKING -{ printf(" rsize = $%X\n", rsize); #endif - return rsize; -#ifdef DEBUG_IMAGE_MARKING + return rsize; } -#endif - return siz; + +// +// Make relocation record for ELF .o file. +// Returns the size of the relocation record. +// +uint32_t CreateELFRelocationRecord(uint8_t * buf, uint8_t * secBuf, uint16_t section) +{ + uint16_t from = 0; // Section fixups are currently FROM + uint32_t rsize = 0; // Size of the relocation table + + // Setup pointer for D_long/word/byte macros + chptr = buf; + ch_size = 0; + + for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext) + { + for(register PTR p=mch->mcptr;;) + { + register uint16_t w = *p.wp++; // w = next mark entry + + if (w & MCHEND) // (end of mark chunk) + break; + + // Get mark record + SYM * symbol = NULL; + uint16_t symFlags = 0; + uint32_t r_offset = *p.lp++; // Mark's location + + if (w & MCHFROM) // Maybe change "from" section + from = *p.wp++; + + if (w & MSYMBOL) // Maybe includes a symbol + { + symbol = *p.sy++; + + if (symbol) + symFlags = symbol->sattr; + } + + // Create relocation record for ELF object, if the mark is in the + // current section. + if (from & section) + { + uint32_t r_sym = 0; + uint32_t r_type = 0; + uint32_t r_addend = 0; + + // Since we're chucking all symbols here for ELF objects by + // default (cf. sect.c), we discriminate here (normally, if + // there is a symbol in the mark record, it means an undefined + // symbol) :-P + if (symbol && !(symFlags & DEFINED) && (symFlags & GLOBAL)) + r_sym = symbol->senv + extraSyms; + else if (w & TEXT) + r_sym = elfHdrNum[ES_TEXT]; // Mark TEXT segment + else if (w & DATA) + r_sym = elfHdrNum[ES_DATA]; // Mark DATA segment + else if (w & BSS) + r_sym = elfHdrNum[ES_BSS]; // Mark BSS segment + + // Set the relocation type next + if (w & MPCREL) + r_type = 5; // R_68K_PC16 + // N.B.: Since we've established that (from & section) is non- + // zero, this condition will *never* be satisfied... :-P + // It might be better to check the symbol's senv; that is, + // if this is a real problem that needs addressing... + else if ((from & section) == 0) + // In the case of a section referring to a label in another + // section (for example text->data) use a R_68K_PC32 mark. + r_type = 4; // R_68K_PC32 + else + r_type = 1; // R_68K_32 + + r_addend = GETBE32(secBuf + r_offset, 0); + + // Deposit the relocation record + D_long(r_offset); + D_long(((r_sym << 8) | r_type)); + D_long(r_addend); + rsize += 0x0C; + } + } + } + + return rsize; }