]> Shamusworld >> Repos - rln/blobdiff - rln.c
Fix to test to see if include paths actually exist.
[rln] / rln.c
diff --git a/rln.c b/rln.c
index 5b3323255551eccfde37216b5e8ce06998fbf5fc..23b2fea77f8df642a65f53f03cb118a47c32f0c8 100644 (file)
--- 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);
 
@@ -2983,7 +3028,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 +3053,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 <fname> <label>      incbin <fname> and set <label>\n");
+       printf("   -i <fname> <label>      incbin <fname> and set <label> (trunc to 8 chars)\n");
+       printf("   -ii <fname> <label>     incbin <fname> and set <label> (no truncation)\n");
        printf("   -l                      add local symbols\n");
        printf("   -m                      produce load symbols map\n");
-       printf("   -n                      output no file header to .abs file\n");
+       printf("   -n                      output no file header to absolute file\n");
        printf("   -o <fname>              set output name\n");
        printf("   -r<size>                section alignment size\n");
        printf("                           w: word (2 bytes)\n");
@@ -3019,7 +3065,7 @@ void ShowHelp(void)
        printf("                           p: phrase (8 bytes, default alignment)\n");
        printf("                           d: double phrase (16 bytes)\n");
        printf("                           q: quad phrase (32 bytes)\n");
-       printf("   -s                      output only global symbols\n");
+       printf("   -s                      output only global symbols (supresses -l)\n");
        printf("   -u                      allow unresolved symbols (experimental)\n");
        printf("   -v                      set verbose mode\n");
        printf("   -w                      show linker warnings\n");
@@ -3069,6 +3115,21 @@ int main(int argc, char * argv[])
                ExitLinker();
        }
 
+       // Check to see if include paths actually exist
+       if (strlen(libdir) > 0)
+       {
+               DIR * test = opendir(libdir);
+
+               if (test == NULL)
+               {
+                       printf("Invalid include path: %s\n", libdir);
+                       errflag = 1;
+                       ExitLinker();
+               }
+
+               closedir(test);
+       }
+
        if (!zflag && !vflag)
        {
                ShowVersion();                          // Display version information