unsigned rflag = 0; // Segment alignment size flag
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, uflag, wflag = 1; // Unimplemented flags
+unsigned pflag, uflag; // Unimplemented flags
unsigned hd = 0; // Index of next file handle to fill
unsigned secalign = 7; // Section Alignment (8=phrase)
unsigned tbase = 0; // TEXT base address
int ost_index = 0; // Index of next ost addition
int endian; // Processor endianess
+// Some human readable defines for endianess
+#define ENDIANNESS_BIG 1
+#define ENDIANNESS_LITTLE 0
+
//
// Get a Long Word from Memory
//
-unsigned getlong(char * src)
+uint32_t getlong(uint8_t * src)
{
- unsigned temp;
- char * out;
+ uint32_t temp;
+ uint8_t * out;
- out = (char *)&temp;
+ out = (uint8_t *)&temp;
- if (endian == 1)
+ if (endian == ENDIANNESS_BIG)
{
*out++ = src[0];
*out++ = src[1];
//
// Put a Long Word into Memory
//
-void putlong(char * dest, unsigned val)
+void putlong(uint8_t * dest, uint32_t val)
{
- *dest++ = (char)(val >> 24);
- *dest++ = (char)(val >> 16);
- *dest++ = (char)(val >> 8);
- *dest = (char)val;
+ *dest++ = (uint8_t)(val >> 24);
+ *dest++ = (uint8_t)(val >> 16);
+ *dest++ = (uint8_t)(val >> 8);
+ *dest = (uint8_t)val;
}
//
// Get a Word from Memory
//
-int getword(char * src)
+uint16_t getword(uint8_t * src)
{
- unsigned temp;
- char * out;
+ uint16_t temp;
+ uint8_t * out;
- out = (char *)&temp;
+ out = (uint8_t *)&temp;
+#if 0
+ // Shamus: This assumes little endian...
*out++ = src[1];
*out++ = src[0];
- *out++ = 0;
- *out = 0;
+// Shamus: And *why* do this as a uint32_t???
+// *out++ = 0;
+// *out = 0;
+#else
+ if (endian == ENDIANNESS_BIG)
+ {
+ out[0] = src[0];
+ out[1] = src[1];
+ }
+ else
+ {
+ out[0] = src[1];
+ out[1] = src[0];
+ }
+#endif
return temp;
}
//
// Put a Word into Memory
//
-void putword(char * dest, int val)
+void putword(uint8_t * dest, uint16_t val)
{
- *dest++ = (char)(val >> 8);
- *dest = (char)val;
+ *dest++ = (uint8_t)(val >> 8);
+ *dest = (uint8_t)val;
}
//
long docommon(void)
{
- struct HREC * hptr; // Hash record pointer
- int i; // Iterator
+ struct HREC * hptr; // Hash record pointer
+ int i; // Iterator
for(i=0; i<NBUCKETS; i++)
{
if (iscommon(hptr->h_type))
{
if (hptr->h_type == 0x03000000)
- hptr->h_type = 0x02000000; // Absolutes can't be externals
+ hptr->h_type = 0x02000000; // Absolutes can't be externals
if (ost_add(hptr->h_sym, hptr->h_type, hptr->h_value) == -1)
return -1;
//
int ost_add(char * name, int type, long value)
{
- int ost_offset_p, ost_offset_e = 0; // OST table offsets for position calcs
- int slen = 0; // Symbol string length
- int ostresult; // OST index result
+ int ost_offset_p, ost_offset_e = 0; // OST table offsets for position calcs
+ int slen = 0; // Symbol string length
+ int ostresult; // OST index result
slen = strlen(name);
ost_offset_p = (ost_ptr - ost);
ost_offset_e = (ost_end - ost);
+ // 3 x int (12)
if ((ost_ptr + 12) > ost_end)
- { // 3 x int (12)
+ {
if ((ost = realloc(ost, (unsigned)(ost_end + OST_BLOCK))) == NULL)
{
printf("OST memory reallocation error.\n");
ost_offset_p = (oststr_ptr - oststr);
ost_offset_e = (oststr_end - oststr);
- if ((oststr_ptr + (slen+1+4)) > oststr_end)
+ if ((oststr_ptr + (slen + 1 + 4)) > oststr_end)
{
if ((oststr = realloc(oststr, (unsigned)(oststr_end + OST_BLOCK))) == NULL)
{
}
}
- // If this is a debug symbol and the include debug symbol flag (-g) is not set then do nothing
+ // If this is a debug symbol and the include debug symbol flag (-g) is not
+ // set then do nothing
if ((type & 0xF0000000) && !gflag)
{
// Do nothing
else
{
ostresult = ost_lookup(name); // Get symbol index in OST
- // If the symbol is in the output symbol table and the bflag is set (don't remove multiply
- // defined locals) and this is not an external/global symbol *** OR *** the symbol is not
- // in the output symbol table then add it.
+
+ // If the symbol is in the output symbol table and the bflag is set
+ // (don't remove multiply defined locals) and this is not an
+ // external/global symbol *** OR *** the symbol is not in the output
+ // symbol table then add it.
if (((ostresult != -1) && bflag && !(type & 0x01000000))
- || ((ostresult != -1) && gflag && (type & 0xF0000000)) || (ostresult == -1))
+ || ((ostresult != -1) && gflag && (type & 0xF0000000)) || (ostresult == -1))
{
if ((type & 0xF0000000) == 0x40000000)
putlong(ost_ptr, 0x00000000); // Zero string table offset for dbg line
putlong(ost_ptr + 8, value);
ost_ptr += 12;
- // If the symbol type is anything but a debug line information symbol then write
- // the symbol string to the string table
+ // If the symbol type is anything but a debug line information
+ // symbol then write the symbol string to the string table
if ((type & 0xF0000000) != 0x40000000)
{
strcpy(oststr_ptr, name); // Put symbol name in string table
}
}
- return 0; // not sure about this as it could affect return indices. needed to stop return error.
+ // not sure about this as it could affect return indices. needed to stop return error.
+ return 0;
}
for(i=0; i<ost_index; i++)
{
- if (!strcmp(oststr + stro, sym))
+ if (strcmp(oststr + stro, sym) == 0)
return i + 1;
- else
- stro += strlen(oststr + stro) + 1;
+
+ stro += strlen(oststr + stro) + 1;
}
return -1;
{
if (ost_add(hptr->h_sym, T_EXT, 0L) == -1)
return 1;
-printf("dounresolved(): added %s\n",hptr->h_sym);
+
+//printf("dounresolved(): added %s\n",hptr->h_sym);
htemp = hptr->h_next; // Temporarily get ptr to next record
free(hptr); // Free current record
hptr = htemp; // Make next record ptr, current
}
// Shamus: Let's output some info to aid in debugging this crap
- if (vflag)
+ if (vflag > 1)
{
- printf("reloc_segment(%d): %s, $%08X: $%08X => $%08X\n",i, (glblreloc ? sym : "(LOCAL)"), addr, olddata, getlong(sptr + addr));
+ char ssiString[128];
+ ssiString[0] = 0;
+
+ if (glblreloc)
+ sprintf(ssiString, " [ssi:%i]", ssidx);
+
+ printf("reloc_segment($%08X): %s, $%08X: $%08X => $%08X%s\n", rflg, (glblreloc ? sym : "(LOCAL)"), addr, olddata, getlong(sptr + addr), ssiString);
}
rptr += 8; // Point to the next relocation record
void put_name(struct OFILE * p)
{
int flag = *(p->o_arname);
- printf("%s%s%s", flag ? p->o_arname : "", flag ? ":" : "", p->o_name);
+ printf("%s%s%s", (flag ? (char *)(p->o_arname) : ""), (flag ? ":" : ""), p->o_name);
}
// Reached maximum file handles
if (hd == NHANDLES)
{
- if (flush_handles()) return 1;
+ if (flush_handles())
+ return 1;
}
// Attempt to open input file
return 1;
}
+ // Shamus: Moar testing...
+ if (vflag > 1)
+ {
+ printf("add_to_hlist(): hptr=$%08X, sym=\"%s\", ofile=$%08X, value=%li, type=%i", (unsigned int)hptr, sym, (unsigned int)ofile, value, type);
+ }
+
for(i=0; i<SYMLEN; i++)
htemp->h_sym[i] = '\0';
while (hptr != NULL)
{
- // if (symcmp(symbol, hptr->h_sym)) <-- left here for giggles :D - LinkoVitch
- if (strcmp(symbol,hptr->h_sym)==0)
+//This is utter failure...
+// if (symcmp(symbol, hptr->h_sym)) <-- left here for giggles :D - LinkoVitch
+ if (strcmp(symbol, hptr->h_sym) == 0)
return hptr;
hptr = hptr->h_next; // Return hash pointer if found
unsigned symtype = 0;
fsize = FSIZE(handle); // Get size of include file
- dsize = (fsize+secalign) & ~secalign; // Round up to a alignment boundary
+ dsize = (fsize + secalign) & ~secalign; // Round up to a alignment boundary
sym1len = strlen(sym1) + 1; // Get sym1 length + null termination
sym2len = strlen(sym2) + 1; // Get sym2 length + null termination
}
// Read in binary data
- if (read(handle, ptr+32, fsize) != fsize)
+ if (read(handle, ptr + 32, fsize) != fsize)
{
printf("File read error on %s\n", fname);
close(handle);
//
int doargs(int argc, char * argv[])
{
- int i = 1; // Iterator
- int c; // Command line character
- char * ifile, * isym; // File name and symbol name for -i
-
- while (i < argc)
- { // Parse through option switches & files
- if (argv[i][0] == '-')
- { // Process command line switches
- if (!argv[i][1])
- {
- printf("Illegal option argument: %s\n\n", argv[i]);
- display_help();
- return 1;
- }
-
- c = argv[i++][1]; // Get next character in command line
-
- switch (c)
- { // Process command line switch
- case '?': // Display usage information
- case 'h':
+ int i = 1; // Iterator
+ int c; // Command line character
+ char * ifile, * isym; // File name and symbol name for -i
+
+ while (i < argc)
+ { // Parse through option switches & files
+ if (argv[i][0] == '-')
+ { // Process command line switches
+ if (!argv[i][1])
+ {
+ printf("Illegal option argument: %s\n\n", argv[i]);
+ display_help();
+ return 1;
+ }
+
+ c = argv[i++][1]; // Get next character in command line
+
+ switch (c)
+ { // Process command line switch
+ case '?': // Display usage information
+ case 'h':
case 'H':
- display_version();
- display_help();
- return 1;
- case 'a':
+ display_version();
+ display_help();
+ return 1;
+ case 'a':
case 'A': // Set absolute linking on
- if (aflag)
- warn('a', 1);
-
- if (i + 2 >= argc)
- {
- printf("Not enough arguments to -a\n");
- return 1;
- }
-
- aflag = 1; // Set abs link flag
- // Segment order is TEXT, DATA, BSS
- // Text segment can be 'r', 'x' or a value
- ttype = 0;
-
- if ((*argv[i] == 'r' || *argv[i] == 'R') && !argv[i][1])
- {
- ttype = -1; // TEXT segment is relocatable
- }
- else if ((*argv[i] == 'x' || *argv[i] == 'X'))
- {
- printf("Error in text-segment address: cannot be contiguous\n");
- return 1;
- }
- else if ((ttype = 0), getval(argv[i], &tval))
- {
- printf("Error in text-segment address: %s is not 'r', 'x' or an address.", argv[i]);
- return 1;
- }
-
- i++;
- // Data segment can be 'r', 'x' or a value
- dtype = 0;
-
- if ((*argv[i] == 'r' || *argv[i] == 'R') && !argv[i][1])
- {
- dtype = -1; // DATA segment is relocatable
- }
- else if ((*argv[i] == 'x' || *argv[i] == 'X'))
- {
- dtype = -2; // DATA follows TEXT
- }
- else if ((dtype = 0), getval(argv[i],&dval))
- {
- printf("Error in data-segment address: %s is not 'r', 'x' or an address.", argv[i]);
- return 1;
- }
-
- i++;
- btype = 0;
-
- // BSS segment can be 'r', 'x' or a value
- if ((*argv[i] == 'r' || *argv[i] == 'R') && !argv[i][1])
- {
- btype = -1; // BSS segment is relocatable
- }
- else if ((*argv[i] == 'x' || *argv[i] == 'X'))
- {
- btype = -3; // BSS follows DATA
- }
- else if ((btype = 0), getval(argv[i],&bval))
- {
- printf("Error in bss-segment address: %s is not 'r', 'x[td]', or an address.", argv[i]);
- return 1;
- }
-
- i++;
- break;
- case 'b':
+ if (aflag)
+ warn('a', 1);
+
+ if (i + 2 >= argc)
+ {
+ printf("Not enough arguments to -a\n");
+ return 1;
+ }
+
+ aflag = 1; // Set abs link flag
+ // Segment order is TEXT, DATA, BSS
+ // Text segment can be 'r', 'x' or a value
+ ttype = 0;
+
+ if ((*argv[i] == 'r' || *argv[i] == 'R') && !argv[i][1])
+ {
+ ttype = -1; // TEXT segment is relocatable
+ }
+ else if ((*argv[i] == 'x' || *argv[i] == 'X'))
+ {
+ printf("Error in text-segment address: cannot be contiguous\n");
+ return 1;
+ }
+ else if ((ttype = 0), getval(argv[i], &tval))
+ {
+ printf("Error in text-segment address: %s is not 'r', 'x' or an address.", argv[i]);
+ return 1;
+ }
+
+ i++;
+ // Data segment can be 'r', 'x' or a value
+ dtype = 0;
+
+ if ((*argv[i] == 'r' || *argv[i] == 'R') && !argv[i][1])
+ {
+ dtype = -1; // DATA segment is relocatable
+ }
+ else if ((*argv[i] == 'x' || *argv[i] == 'X'))
+ {
+ dtype = -2; // DATA follows TEXT
+ }
+ else if ((dtype = 0), getval(argv[i],&dval))
+ {
+ printf("Error in data-segment address: %s is not 'r', 'x' or an address.", argv[i]);
+ return 1;
+ }
+
+ i++;
+ btype = 0;
+
+ // BSS segment can be 'r', 'x' or a value
+ if ((*argv[i] == 'r' || *argv[i] == 'R') && !argv[i][1])
+ {
+ btype = -1; // BSS segment is relocatable
+ }
+ else if ((*argv[i] == 'x' || *argv[i] == 'X'))
+ {
+ btype = -3; // BSS follows DATA
+ }
+ else if ((btype = 0), getval(argv[i],&bval))
+ {
+ printf("Error in bss-segment address: %s is not 'r', 'x[td]', or an address.", argv[i]);
+ return 1;
+ }
+
+ i++;
+ break;
+ case 'b':
case 'B': // Don't remove muliply defined locals
- if (bflag)
- warn('b', 1);
+ if (bflag)
+ warn('b', 1);
- bflag = 1;
- break;
- case 'c':
+ bflag = 1;
+ break;
+ case 'c':
case 'C': // Process a command file
- if (i == argc)
- {
- printf("Not enough arguments to -c\n");
- return 1;
- }
-
- if (docmdfile(argv[i++]))
- {
- return 1;
- }
-
- break;
- case 'd':
+ if (i == argc)
+ {
+ printf("Not enough arguments to -c\n");
+ return 1;
+ }
+
+ if (docmdfile(argv[i++]))
+ {
+ return 1;
+ }
+
+ break;
+ case 'd':
case 'D': // Wait for "return" before exiting
- if (dflag)
- warn('d', 0);
+ if (dflag)
+ warn('d', 0);
- dflag = 1;
- waitflag = 1;
- break;
- case 'e':
+ dflag = 1;
+ waitflag = 1;
+ break;
+ case 'e':
case 'E': // Output COFF (absolute only)
- cflag = 1;
- break;
- case 'g':
+ cflag = 1;
+ break;
+ case 'g':
case 'G': // Output source level debugging
- printf("\'g\' flag not currently implemented\n");
- gflag = 0;
- /*
- if (gflag) warn('g', 1);
- gflag = 1;
- */
- break;
- case 'i':
+ printf("\'g\' flag not currently implemented\n");
+ gflag = 0;
+ /*
+ if (gflag) warn('g', 1);
+ gflag = 1;
+ */
+ break;
+ case 'i':
case 'I': // Include binary file
- if (i + 2 > argc)
- {
- printf("Not enough arguments to -i\n");
- return 1;
- }
-
- ifile = argv[i++];
- isym = argv[i++];
-
- if ((argv[i-3][2] == 'i') || (argv[i-3][2] == 'I'))
- { // handle -ii (No truncation)
- if (!cflag)
- printf("warning: (-ii) COFF format output not specified\n");
- }
- else
- { // handle -i (Truncation)
- if (strlen(isym) > 7)
- isym[7] = '\0';
- }
-
- // Place include files in the DATA segment only
- if (dofile(ifile, DSTSEG_D, isym))
- return 1;
-
- break;
- case 'l':
+ if (i + 2 > argc)
+ {
+ printf("Not enough arguments to -i\n");
+ return 1;
+ }
+
+ ifile = argv[i++];
+ isym = argv[i++];
+
+ if ((argv[i-3][2] == 'i') || (argv[i-3][2] == 'I'))
+ { // handle -ii (No truncation)
+ if (!cflag)
+ printf("warning: (-ii) COFF format output not specified\n");
+ }
+ else
+ { // handle -i (Truncation)
+ if (strlen(isym) > 7)
+ isym[7] = '\0';
+ }
+
+ // Place include files in the DATA segment only
+ if (dofile(ifile, DSTSEG_D, isym))
+ return 1;
+
+ break;
+ case 'l':
case 'L': // Add local symbols
- if (lflag)
- warn('l', 1);
+ if (lflag)
+ warn('l', 1);
- lflag = 1;
- break;
- case 'm':
+ lflag = 1;
+ break;
+ case 'm':
case 'M': // Produce load symbol map
- if (mflag)
- warn('m', 1);
+ if (mflag)
+ warn('m', 1);
- mflag = 1;
- break;
- case 'n':
+ mflag = 1;
+ break;
+ case 'n':
case 'N': // Output no header to .abs file
- if (noheaderflag)
- warn('n', 1);
+ if (noheaderflag)
+ warn('n', 1);
- noheaderflag = 1;
- break;
- case 'o':
+ noheaderflag = 1;
+ break;
+ case 'o':
case 'O': // Specify an output file
- if (oflag)
- warn('o', 1);
-
- oflag = 1;
-
- if (i >= argc)
- {
- printf("No output filename following -o switch\n");
- return 1;
- }
-
- if (strlen(argv[i]) > FARGSIZE - 5)
- {
- printf("Output file name too long (sorry!)\n");
- return 1;
- }
-
- strcpy(ofile, argv[i++]);
- break;
- case 'r':
+ if (oflag)
+ warn('o', 1);
+
+ oflag = 1;
+
+ if (i >= argc)
+ {
+ printf("No output filename following -o switch\n");
+ return 1;
+ }
+
+ if (strlen(argv[i]) > FARGSIZE - 5)
+ {
+ printf("Output file name too long (sorry!)\n");
+ return 1;
+ }
+
+ strcpy(ofile, argv[i++]);
+ break;
+ case 'r':
case 'R': // Section alignment size
- if (rflag)
- warn('r', 1);
-
- rflag = 1;
-
- switch (argv[i-1][2])
- {
- case 'w': case 'W': secalign = 1; break; // Word alignment
- case 'l': case 'L': secalign = 3; break; // Long alignment
- case 'p': case 'P': secalign = 7; break; // Phrase alignment
- case 'd': case 'D': secalign = 15; break; // Double phrase alignment
- case 'q': case 'Q': secalign = 31; break; // Quad phrase alignment
- default: secalign = 7; break; // Default phrase alignment
- }
-
- break;
- case 's':
+ if (rflag)
+ warn('r', 1);
+
+ rflag = 1;
+
+ switch (argv[i-1][2])
+ {
+ case 'w': case 'W': secalign = 1; break; // Word alignment
+ case 'l': case 'L': secalign = 3; break; // Long alignment
+ case 'p': case 'P': secalign = 7; break; // Phrase alignment
+ case 'd': case 'D': secalign = 15; break; // Double phrase alignment
+ case 'q': case 'Q': secalign = 31; break; // Quad phrase alignment
+ default: secalign = 7; break; // Default phrase alignment
+ }
+
+ break;
+ case 's':
case 'S': // Output only global symbols
- if (sflag)
- warn('s', 1);
+ if (sflag)
+ warn('s', 1);
- sflag = 1;
- break;
- case 'v':
+ sflag = 1;
+ break;
+ case 'v':
case 'V': // Verbose information
- if (!vflag && !versflag)
- {
- display_version();
- }
-
- vflag++;
- break;
- case 'z':
+ if (!vflag && !versflag)
+ {
+ display_version();
+ }
+
+ vflag++;
+ break;
+ case 'w':
+ case 'W': // Show warnings flag
+ if (wflag)
+ warn('w', 1);
+
+ wflag = 1;
+ break;
+ case 'z':
case 'Z': // Suppress banner flag
- if (zflag)
- warn('z', 1);
-
- zflag = 1;
- break;
- default:
- printf("unknown option argument `%c'\n", c);
- return 1;
- }
- }
- else
- { // Not a switch, then process as a file
- if (dofile(argv[i++], 0, NULL))
- return 1;
- }
-
- }
-
- if (!oflag && vflag)
- {
- strcpy(ofile, "output");
- printf("Output file is %s[.ext]\n", ofile);
- }
-
- if (oflag && vflag)
- printf("Output file is %s\n", ofile);
-
- if (sflag)
- lflag = 0;
-
- return 0; // No problems encountered
+ if (zflag)
+ warn('z', 1);
+
+ zflag = 1;
+ break;
+ default:
+ printf("unknown option argument `%c'\n", c);
+ return 1;
+ }
+ }
+ else
+ { // Not a switch, then process as a file
+ if (dofile(argv[i++], 0, NULL))
+ return 1;
+ }
+
+ }
+
+ if (!oflag && vflag)
+ {
+ strcpy(ofile, "output");
+ printf("Output file is %s[.ext]\n", ofile);
+ }
+
+ if (oflag && vflag)
+ printf("Output file is %s\n", ofile);
+
+ if (sflag)
+ lflag = 0;
+
+ return 0; // No problems encountered
}
printf(" q: quad phrase (32 bytes)\n");
printf(" -s output only global symbols\n");
printf(" -v set verbose mode\n");
+ printf(" -w show linker warnings\n");
printf(" -z suppress banner\n");
printf("\n");
}
// Wait for return key if requested
if (waitflag)
{
- printf("\nPress the <return> key to continue. ");
+ printf("\nPress the [RETURN] key to continue. ");
fgets(tempbuf, 128, stdin);
}
char * p = (char *)&i;
if (p[0] == 1)
- return 0; // LITTLE
+ return ENDIANNESS_LITTLE;
- return 1; // BIG
+ return ENDIANNESS_BIG;
}
printf("Absolute linking ");
if (cflag)
- printf("(COF)\n");
+ printf("(COF)\n");
else
- printf("(ABS)\n");
+ printf("(ABS)\n");
}
if (vflag > 1)
printf("+---------+----------+----------+----------+\n\n");
}
+//printf("BIG_ENDIAN = %i, LITTLE_ENDIAN = %i\n", BIG_ENDIAN, LITTLE_ENDIAN);
+
free(header); // Free allocated memory
rln_exit(); // Perform application exit
}