Blob Blame History Raw
diff --git a/gputils/gpstrip.c b/gputils/gpstrip.c
index dce5ddb..06b7d97 100644
--- a/gputils/gpstrip.c
+++ b/gputils/gpstrip.c
@@ -92,7 +92,7 @@ _conditional_remove(gp_symbol_t *Symbol)
       gp_message("removing symbol \"%s\"", Symbol->name);
     }
 
-    gp_coffgen_del_symbol(state.object, Symbol);
+    gp_coffgen_del_symbol(state.object, Symbol, true);
   }
 }
 
diff --git a/libgputils/gpcoffgen.c b/libgputils/gpcoffgen.c
index 8ebcf15..dc60348 100644
--- a/libgputils/gpcoffgen.c
+++ b/libgputils/gpcoffgen.c
@@ -346,7 +346,7 @@ gp_coffgen_del_section_symbols(gp_object_t *Object, gp_section_t *Section)
     list   = list->next;
 
     if (symbol->section == Section) {
-      gp_coffgen_del_symbol(Object, symbol);
+      gp_coffgen_del_symbol(Object, symbol, true);
     }
   }
 }
@@ -732,8 +732,10 @@ gp_coffgen_move_reserve_symbol(gp_object_t *Object, gp_symbol_t *Symbol)
 /* Delete the symbol from the object. */
 
 gp_boolean
-gp_coffgen_del_symbol(gp_object_t *Object, gp_symbol_t *Symbol)
+gp_coffgen_del_symbol(gp_object_t *Object, gp_symbol_t *Symbol, gp_boolean Touch_number)
 {
+  unsigned int n_deleted;
+
   if (Object->symbol_list.first == NULL) {
     return false;
   }
@@ -745,7 +747,13 @@ gp_coffgen_del_symbol(gp_object_t *Object, gp_symbol_t *Symbol)
   }
 
   gp_list_node_remove(&Object->symbol_list, Symbol);
-  Object->num_symbols -= 1 + gp_coffgen_free_symbol(Symbol);
+
+  n_deleted = 1 + gp_coffgen_free_symbol(Symbol);
+
+  if (Touch_number) {
+    Object->num_symbols -= n_deleted;
+  }
+
   return true;
 }
 
@@ -999,7 +1007,7 @@ _check_section_relocations(proc_class_t Class, gp_section_t *Section, unsigned i
     if (sym_sect == NULL) {
       /* This is an orphan symbol. */
       if (FlagIsClr(Behavior, RELOC_DISABLE_WARN)) {
-        if (FlagIsSet(Behavior, RELOC_ENABLE_CINIT_WARN) || (strcmp(symbol->name, "_cinit") != 0)) {
+        if (FlagIsSet(Behavior, RELOC_ENABLE_CINIT_WARN) && (strcmp(symbol->name, "_cinit") != 0)) {
           gp_warning("Relocation symbol \"%s\" [0x%0*X] has no section. (pass %u)",
                      symbol->name, Class->addr_digits, relocation->address, Pass);
         }
diff --git a/libgputils/gpcoffgen.h b/libgputils/gpcoffgen.h
index ffb5b5c..41d3f89 100644
--- a/libgputils/gpcoffgen.h
+++ b/libgputils/gpcoffgen.h
@@ -73,7 +73,7 @@ extern gp_symbol_t *gp_coffgen_add_symbol(gp_object_t *Object, const char *Name,
 extern gp_aux_t *gp_coffgen_add_aux(gp_object_t *Object, gp_symbol_t *Symbol);
 extern gp_aux_t *gp_coffgen_make_block_aux(gp_symbol_t *Symbol, unsigned int Num_auxsyms);
 extern gp_symbol_t *gp_coffgen_move_reserve_symbol(gp_object_t *Object, gp_symbol_t *Symbol);
-extern gp_boolean gp_coffgen_del_symbol(gp_object_t *Object, gp_symbol_t *Symbol);
+extern gp_boolean gp_coffgen_del_symbol(gp_object_t *Object, gp_symbol_t *Symbol, gp_boolean Touch_number);
 extern gp_symbol_t **gp_coffgen_make_symbol_array(const gp_object_t *Object, int (*Cmp)(const void *, const void *));
 extern const char *gp_coffgen_symbol_type_to_str(uint8_t Type);
 extern const char *gp_coffgen_symbol_derived_type_to_str(uint32_t Type);
diff --git a/libgputils/gpcofflink.c b/libgputils/gpcofflink.c
index 7511c36..1283e63 100644
--- a/libgputils/gpcofflink.c
+++ b/libgputils/gpcofflink.c
@@ -174,9 +174,12 @@ gp_cofflink_clean_table(gp_object_t *Object, symbol_table_t *Symbols)
   const gp_coffsymbol_t *var;
   const symbol_t        *sym;
   gp_symbol_t           *next;
+  int                    num_clean_errors;
 
   gp_debug("Cleaning symbol table.");
 
+  num_clean_errors = gp_real_num_errors();
+
   /* point all relocations to the symbol definitions */
   section = Object->section_list.first;
   while (section != NULL) {
@@ -186,13 +189,17 @@ gp_cofflink_clean_table(gp_object_t *Object, symbol_table_t *Symbols)
 
       if (gp_coffgen_is_external_symbol(symbol)) {
         /* This is an external symbol defined elsewhere. */
-        sym    = gp_sym_get_symbol(Symbols, symbol->name);
-        assert(sym != NULL);
-        var    = (const gp_coffsymbol_t *)gp_sym_get_symbol_annotation(sym);
-        assert(var != NULL);
-        symbol = var->symbol;
-        assert(symbol != NULL);
-        relocation->symbol = symbol;
+        sym = gp_sym_get_symbol(Symbols, symbol->name);
+        if (sym == NULL) {
+          gp_error("Non-existent external symbol - \"%s\" - used in \"%s\" section.", symbol->name, section->name);
+        }
+        else {
+          var    = (const gp_coffsymbol_t *)gp_sym_get_symbol_annotation(sym);
+          assert(!(var == NULL));
+          symbol = var->symbol;
+          assert(!(symbol == NULL));
+          relocation->symbol = symbol;
+        }
       }
 
       relocation = relocation->next;
@@ -201,13 +208,17 @@ gp_cofflink_clean_table(gp_object_t *Object, symbol_table_t *Symbols)
     section = section->next;
   }
 
+  if (gp_real_num_errors() > num_clean_errors) {
+    exit(1);
+  }
+
   symbol = Object->symbol_list.first;
   while (symbol != NULL) {
     next = symbol->next;
 
     if (gp_coffgen_is_external_symbol(symbol)) {
       gp_debug("  removed symbol \"%s\"", symbol->name);
-      gp_coffgen_del_symbol(Object, symbol);
+      gp_coffgen_del_symbol(Object, symbol, true);
     }
 
     symbol = next;
@@ -265,7 +276,7 @@ gp_cofflink_combine_overlay(gp_object_t *Object, gp_boolean Remove_symbol)
 
         /* Remove the section symbol. */
         if (Remove_symbol) {
-          gp_coffgen_del_symbol(Object, second->symbol);
+          gp_coffgen_del_symbol(Object, second->symbol, true);
         }
 
         /* Update the symbol table */
@@ -1570,6 +1581,7 @@ _patch_addr(gp_object_t *Object, gp_section_t *Section, const gp_reloc_t *Reloca
   int                bank;
   int                page;
   gp_boolean         write_data;
+  const insn_t      *instruction;
 
   class     = Object->class;
   num_pages = gp_processor_num_pages(Object->processor);
@@ -1602,9 +1614,23 @@ _patch_addr(gp_object_t *Object, gp_section_t *Section, const gp_reloc_t *Reloca
       data = class->reloc_goto(value);
       break;
 
-    case RELOC_LOW:
-      data = value & 0xff;
+    case RELOC_LOW: {
+      instruction = class->find_insn(class, current_value);
+
+      if (instruction == NULL)  {
+        gp_error("No instruction for %#x at %#x(%s/%s)", current_value,
+                 byte_addr, Section->name, symbol->name);
+        return;
+      }
+
+      if (instruction->class == INSN_CLASS_LIT8) {
+        data = value & 0xff;
+      }
+      else {
+        data = class->reloc_f(value);
+      }
       break;
+    }
 
     case RELOC_HIGH:
       data = class->reloc_high(FlagIsSet(symbol->section->flags, STYP_ROM_AREA), value);
diff --git a/libgputils/gpmessage.c b/libgputils/gpmessage.c
index 0a640eb..1573193 100644
--- a/libgputils/gpmessage.c
+++ b/libgputils/gpmessage.c
@@ -34,14 +34,20 @@ int gp_num_errors   = 0;
 int gp_num_warnings = 0;
 int gp_num_messages = 0;
 
+static int _real_num_errors   = 0;
+static int _real_num_warnings = 0;
+static int _real_num_messages = 0;
+
 /*------------------------------------------------------------------------------------------------*/
 
 void
-gp_error(const char *Format, ...)
+gp_error(const char* Format, ...)
 {
   va_list args;
   char    buffer[BUFSIZ];
 
+  _real_num_errors++;
+
   if (gp_message_disable) {
     return;
   }
@@ -62,11 +68,13 @@ gp_error(const char *Format, ...)
 /*------------------------------------------------------------------------------------------------*/
 
 void
-gp_warning(const char *Format, ...)
+gp_warning(const char* Format, ...)
 {
   va_list args;
   char    buffer[BUFSIZ];
 
+  _real_num_warnings++;
+
   if (gp_message_disable) {
     return;
   }
@@ -87,11 +95,13 @@ gp_warning(const char *Format, ...)
 /*------------------------------------------------------------------------------------------------*/
 
 void
-gp_message(const char *Format, ...)
+gp_message(const char* Format, ...)
 {
   va_list args;
   char    buffer[BUFSIZ];
 
+  _real_num_messages++;
+
   if (gp_message_disable) {
     return;
   }
@@ -112,7 +122,7 @@ gp_message(const char *Format, ...)
 /*------------------------------------------------------------------------------------------------*/
 
 void
-gp_debug(const char *Format, ...)
+gp_debug(const char* Format, ...)
 {
   va_list args;
   char    buffer[BUFSIZ];
@@ -131,3 +141,27 @@ gp_debug(const char *Format, ...)
 
   printf("debug: %s\n", buffer);
 }
+
+/*------------------------------------------------------------------------------------------------*/
+
+int
+gp_real_num_errors(void)
+{
+  return _real_num_errors;
+}
+
+/*------------------------------------------------------------------------------------------------*/
+
+int
+gp_real_num_warnings(void)
+{
+  return _real_num_warnings;
+}
+
+/*------------------------------------------------------------------------------------------------*/
+
+int
+gp_real_num_messages(void)
+{
+  return _real_num_messages;
+}
diff --git a/libgputils/gpmessage.h b/libgputils/gpmessage.h
index d2f6ffa..2329f4c 100644
--- a/libgputils/gpmessage.h
+++ b/libgputils/gpmessage.h
@@ -30,9 +30,13 @@ extern int gp_num_errors;
 extern int gp_num_warnings;
 extern int gp_num_messages;
 
-extern void gp_error(const char *Format, ...);
-extern void gp_warning(const char *Format, ...);
-extern void gp_message(const char *Format, ...);
-extern void gp_debug(const char *Format, ...);
+extern void gp_error(const char* Format, ...);
+extern void gp_warning(const char* Format, ...);
+extern void gp_message(const char* Format, ...);
+extern void gp_debug(const char* Format, ...);
+
+extern int gp_real_num_errors(void);
+extern int gp_real_num_warnings(void);
+extern int gp_real_num_messages(void);
 
 #endif
diff --git a/libgputils/gpreadobj.c b/libgputils/gpreadobj.c
index f1cc22d..57de3f0 100644
--- a/libgputils/gpreadobj.c
+++ b/libgputils/gpreadobj.c
@@ -648,7 +648,7 @@ _clean_symbol_table(gp_object_t *Object)
       for (i = 0; i < curr_symbol->aux_list.num_nodes; ++i) {
         aux_symbol  = next_symbol;
         next_symbol = next_symbol->next;
-        gp_coffgen_del_symbol(Object, aux_symbol);
+        gp_coffgen_del_symbol(Object, aux_symbol, false);
       }
     }
     curr_symbol = curr_symbol->next;