X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rln;a=blobdiff_plain;f=rln.c;h=37e5197921c8be3bfd2669f65ffee66c72c4b285;hp=5b3323255551eccfde37216b5e8ce06998fbf5fc;hb=e0c5bd18176b70031fd7fce877c6ca1d8b093a8c;hpb=9ab479822c5e31c7cee4cad1496b562b42ee374b diff --git a/rln.c b/rln.c index 5b33232..37e5197 100644 --- a/rln.c +++ b/rln.c @@ -1,6 +1,6 @@ // // RLN - Reboot's Linker for the Atari Jaguar console system -// Copyright (C) 199x, Allan K. Pratt, 2014-2015 Reboot & Friends +// Copyright (C) 199x, Allan K. Pratt, 2014-2018 Reboot & Friends // #include "rln.h" @@ -22,7 +22,7 @@ unsigned sflag = 0; // Output only global symbols unsigned vflag = 0; // Verbose flag unsigned wflag = 0; // Show warnings flag unsigned zflag = 0; // Suppress banner flag -unsigned pflag = 0, uflag = 0; // Unimplemented flags +unsigned pflag = 0, uflag = 0; // Unimplemented flags (partial link, don't abort on unresolved symbols) unsigned hd = 0; // Index of next file handle to fill unsigned secalign = 7; // Section Alignment (8=phrase) unsigned tbase = 0; // TEXT base address @@ -71,6 +71,10 @@ struct HREC * LookupHREC(char *); char * PathTail(char *); void ShowHelp(void); void ShowVersion(void); +int OSTLookup(char * sym); +int OSTAdd(char * name, int type, long value); +int ProcessFiles(void); +int doargs(int argc, char * argv[]); // @@ -585,8 +589,12 @@ int RelocateSegment(struct OFILE * ofile, int flag) unsigned glblreloc; // Global relocation flag unsigned absreloc; // Absolute relocation flag unsigned relreloc; // Relative relocation flag + unsigned wordreloc; // Relocate word only flag + unsigned opreloc; // Relocate OP data address only flag unsigned swcond; // Switch statement condition unsigned relocsize; // Relocation record size + unsigned saveBits; // OP data leftover bits save + unsigned saveBits2; // If there is no TEXT relocation data for the selected object file segment // then update the COF TEXT segment offset allowing for the phrase padding @@ -664,8 +672,10 @@ int RelocateSegment(struct OFILE * ofile, int flag) addr = GetLong(rptr); rflg = GetLong(rptr + 4); glblreloc = (rflg & 0x00000010 ? 1 : 0);// Set global relocation flag - absreloc = (rflg & 0x00000040 ? 1 : 0); // Set absolute relocation flag - relreloc = (rflg & 0x000000A0 ? 1 : 0); // Set relative relocation flag + absreloc = (rflg & 0x00000040 ? 1 : 0); // Set absolute relocation flag + relreloc = (rflg & 0x000000A0 ? 1 : 0); // Set relative relocation flag + wordreloc = (rflg & 0x00000002 ? 1 : 0); // Set word relocation flag + opreloc = (rflg & 0x00000004 ? 1 : 0); // Set OP relocation flag // Additional processing required for global relocations if (glblreloc) @@ -682,9 +692,22 @@ int RelocateSegment(struct OFILE * ofile, int flag) newdata = GetLong(ost + ((ssidx - 1) * 12) + 8); } - // Obtain the existing long word segment data and flip words if the - // relocation flags indicate it relates to a RISC MOVEI instruction - olddata = GetLong(sptr + addr); + // Obtain the existing long word (or word) segment data and flip words + // if the relocation flags indicate it relates to a RISC MOVEI + // instruction + olddata = (wordreloc ? GetWord(sptr + addr) : GetLong(sptr + addr)); + + // If it's a OP QUAD relocation, get the data out of the DATA bits. + // Note that because we can't afford to lose the bottom 3 bits of the + // relocation record, we lose 3 off the top--which means the maximum + // this can store is $1FFFF8 (vs. $FFFFF8). + if (opreloc) + { + saveBits2 = (GetLong(sptr + addr + 8) & 0xE0000000) >> 8; // Upper 3 of data addr + saveBits = olddata & 0x7FF; + olddata = (olddata & 0xFFFFF800) >> 11; + olddata |= saveBits2; // Restore upper 3 bits of data addr + } if (rflg & 0x01) olddata = _SWAPWORD(olddata); @@ -703,7 +726,7 @@ int RelocateSegment(struct OFILE * ofile, int flag) break; case 0x00000400: // TEXT segment relocation record // SCPCD : the symbol point to a text segment, we should use the textoffset - newdata = tbase + textoffset + olddata; + newdata = tbase + textoffset + olddata; break; case 0x00000600: // DATA segment relocation record @@ -734,7 +757,21 @@ int RelocateSegment(struct OFILE * ofile, int flag) if (rflg & 0x01) newdata = _SWAPWORD(newdata); - PutLong(sptr + addr, newdata); + if (wordreloc) + PutWord(sptr + addr, newdata); + else if (opreloc) + { + if (vflag > 1) + printf("OP reloc: oldata=$%X, newdata=$%X\n", olddata, newdata); + + newdata = ((newdata & 0x00FFFFF8) << 8) | saveBits; + PutLong(sptr + addr, newdata); + // Strip out extraneous data hitchhikers from 2nd phrase... + newdata = GetLong(sptr + addr + 8) & 0x007FFFFF; + PutLong(sptr + addr + 8, newdata); + } + else + PutLong(sptr + addr, newdata); } else if (relreloc) { @@ -1050,11 +1087,11 @@ int WriteOutputFile(struct OHEADER * header) if (strchr(ofile, '.') == NULL) { if (aflag && cflag) - strcat(ofile, ".cof"); // COF files + strcat(ofile, ".cof"); // COF files (a type of abs) else if (aflag && !cflag) strcat(ofile, ".abs"); // ABS files else - strcat(ofile, ".o"); // Object files (partial linking etc) + strcat(ofile, ".o"); // Object files (partial linking, etc) } FILE * fd = fopen(ofile, "wb"); // Attempt to open output file @@ -1157,18 +1194,20 @@ int WriteOutputFile(struct OHEADER * header) } // Write the header, but not if noheaderflag - // Absolute (ABS) header - if (!cflag) + if (!noheaderflag) { - if (!noheaderflag) + // Absolute (ABS) header + if (!cflag) + { if (fwrite(himage, 36, 1, fd) != 1) goto werror; - } - // Absolute (COF) header - else - { - if (fwrite(himage, 168, 1, fd) != 1) - goto werror; + } + // Absolute (COF) header + else + { + if (fwrite(himage, 168, 1, fd) != 1) + goto werror; + } } // Write the TEXT segment of each object file @@ -1215,7 +1254,12 @@ int WriteOutputFile(struct OHEADER * header) } } - if (!noheaderflag) +//wha? if (!noheaderflag) + // This isn't quite right, but it's closer... + // (the l and s flags tell the linker to output local & global symbols + // in the symbol table, so it seems there's some other thing that's a + // default set somewhere. Not 100% sure. Setting -s kills -l, BTW...) + if (lflag || sflag) { // Write the symbols table and string table // Absolute (COF) symbol/string table @@ -2404,7 +2448,8 @@ int LoadArchive(char * fname, int fd) } // Check to see if a long filename was requested - if (objName[0] == 0x20) + // N.B.: " " is for GNU archives, and "/" is for BSD archives + if ((objName[0] == 0x20) || (objName[0] == '/')) { uint32_t fnSize = atoi(objName + 1); @@ -2932,6 +2977,22 @@ int doargs(int argc, char * argv[]) wflag = 1; break; + case 'y': + case 'Y': + if (i >= argc) + { + printf("No directory filename following -y switch\n"); + return 1; + } + + if (strlen(argv[i]) > FARGSIZE * 3) + { + printf("Directory file name too long (sorry!)\n"); + return 1; + } + + strcpy(libdir, argv[i++]); + break; case 'z': case 'Z': // Suppress banner flag if (zflag) @@ -2983,7 +3044,7 @@ void ShowVersion(void) "| | | | | | |\n" "|_| |_|_| |_|\n" "\nReboot's Linker for Atari Jaguar\n" - "Copyright (c) 199x Allan K. Pratt, 2014-2015 Reboot\n" + "Copyright (c) 199x Allan K. Pratt, 2014-2018 Reboot\n" "V%i.%i.%i %s (%s)\n\n", MAJOR, MINOR, PATCH, __DATE__, PLATFORM); } } @@ -3008,10 +3069,11 @@ void ShowHelp(void) printf(" -d wait for key after link\n"); printf(" -e output COF absolute file\n"); printf(" -g output source-level debugging\n"); - printf(" -i