Browse Source

Implement --remove-unused in the presence of debugging information.
Fix omission of .debug_ranges.


git-svn-id: file:///var/svn/tigccpp/trunk/tigcc/ld-tigcc@219 9552661e-59e3-4036-b4f2-dbe53926924f

kevinkofler 19 years ago
parent
commit
06b5e61e83
5 changed files with 72 additions and 20 deletions
  1. 8 5
      data.h
  2. 8 6
      export/exp_dbg.c
  3. 29 4
      gcunused.c
  4. 2 0
      import/imp_coff.c
  5. 25 5
      main.c

+ 8 - 5
data.h

@@ -52,6 +52,7 @@ typedef enum {PT_NATIVE = 1, PT_NOSTUB = 2, PT_KERNEL = 0, PT_NOSTUB_DLL = 3, PT
 
 // Debugging Information Section Type Enumeration
 // DI_NONE:           Not debugging information (same as FALSE)
+// DI_DELETED:        Deleted section (referenced from debugging info only)
 // DI_STAB:           Stabs symbol table
 // DI_STABSTR:        Stabs string table
 // DI_DEBUG_ABBREV:   DWARF 2 .debug_abbrev section
@@ -62,14 +63,16 @@ typedef enum {PT_NATIVE = 1, PT_NOSTUB = 2, PT_KERNEL = 0, PT_NOSTUB_DLL = 3, PT
 // DI_DEBUG_LOC:      DWARF 2 .debug_loc section
 // DI_DEBUG_MACINFO:  DWARF 2 .debug_macinfo section
 // DI_DEBUG_PUBNAMES: DWARF 2 .debug_pubnames section
+// DI_DEBUG_RANGES:   DWARF 2 .debug_ranges section
 // DI_DEBUG_STR:      DWARF 2 .debug_str section
 // DI_EH_FRAME:       DWARF 2 .eh_frame section (used only for debugging in TIGCC)
 // DI_LAST:           Last debugging information type, for iterating purposes
-typedef enum {DI_NONE = FALSE, DI_STAB = 1, DI_STABSTR = 2, DI_DEBUG_ABBREV = 3,
-              DI_DEBUG_ARANGES = 4, DI_DEBUG_FRAME = 5, DI_DEBUG_INFO = 6,
-              DI_DEBUG_LINE = 7, DI_DEBUG_LOC = 8, DI_DEBUG_MACINFO = 9,
-              DI_DEBUG_PUBNAMES = 10, DI_DEBUG_STR = 11, DI_EH_FRAME = 12,
-              DI_LAST = 12} DebuggingInfoTypes;
+typedef enum {DI_NONE = FALSE, DI_DELETED = 1, DI_STAB = 2, DI_STABSTR = 3,
+              DI_DEBUG_ABBREV = 4, DI_DEBUG_ARANGES = 5, DI_DEBUG_FRAME = 6,
+              DI_DEBUG_INFO = 7, DI_DEBUG_LINE = 8, DI_DEBUG_LOC = 9,
+              DI_DEBUG_MACINFO = 10, DI_DEBUG_PUBNAMES = 11,
+              DI_DEBUG_RANGES = 12, DI_DEBUG_STR = 13, DI_EH_FRAME = 14,
+              DI_LAST = 14} DebuggingInfoTypes;
 
 typedef I4 VERSION;
 

+ 8 - 6
export/exp_dbg.c

@@ -50,7 +50,7 @@
 #include <string.h>
 
 #define MAX_NAMED_SECTION (3+DI_LAST)
-#define FIRST_SECTION_ID_WITH_ZERO_VADDR 3
+#define FIRST_SECTION_ID_WITH_ZERO_VADDR 4
 
 typedef struct {
 	OFFSET FileOffset;
@@ -64,11 +64,12 @@ static OFFSET VAddrs[MAX_NAMED_SECTION+1];
 static COUNT SectionID;
 
 static const char *SectionFullNames[MAX_NAMED_SECTION] =
-                  {".text", ".data", ".bss", ".stab", ".stabstr",
+                  {".text", ".data", ".bss", ".deleted", ".stab", ".stabstr",
                    ".debug_abbrev", ".debug_aranges",
                    ".debug_frame", ".debug_info", ".debug_line",
                    ".debug_loc", ".debug_macinfo",
-                   ".debug_pubnames", ".debug_str", ".eh_frame"};
+                   ".debug_pubnames", ".debug_ranges", ".debug_str",
+                   ".eh_frame"};
 
 // These really ought to be written in LISP rather than C, but...
 static void ApplyIfNonNull(void (*f)(const SECTION *, void *),
@@ -215,11 +216,12 @@ static void CountSymbolTableOffset (const SECTION *Section, void *UserData)
 static void WriteSectionHeader (const SECTION *Section, void *UserData)
 {
 	static const char SectionNames[MAX_NAMED_SECTION][COFF_SECTION_NAME_LEN] =
-	                  {".text", ".data", ".bss", ".stab", ".stabstr",
-	                   ".debug_a"/*bbrev*/, ".debug_a"/*ranges*/,
+	                  {".text", ".data", ".bss", ".deleted", ".stab",
+	                   ".stabstr", ".debug_a"/*bbrev*/, ".debug_a"/*ranges*/,
 	                   ".debug_f"/*rame*/, ".debug_i"/*nfo*/, ".debug_l"/*ine*/,
 	                   ".debug_l"/*oc*/, ".debug_m"/*acinfo*/,
-	                   ".debug_p"/*ubnames*/, ".debug_s"/*tr*/, ".eh_fram"/*e*/};
+	                   ".debug_p"/*ubnames*/, ".debug_r"/*anges*/,
+	                   ".debug_s"/*tr*/, ".eh_fram"/*e*/};
 	static const I4 SectionFlags[MAX_NAMED_SECTION] =
 	                {COFF_SECTION_TEXT, COFF_SECTION_DATA, COFF_SECTION_BSS, 0,
 	                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

+ 29 - 4
gcunused.c

@@ -37,8 +37,9 @@ static void MarkSection (SECTION *Section)
 {
 	RELOC *Reloc;
 
-	// If the section is already marked, return immediately.
-	if (Section->Referenced)
+	// If the section is already marked, or if it is a debugging information
+	// section, return immediately.
+	if (Section->Referenced || Section->DebuggingInfoType)
 		return;
 
 	// Mark the section right now to avoid infinite recursion.
@@ -89,8 +90,14 @@ static void RemoveSectionIfUnused (SECTION *Section)
 NextLibCall:;
 	}
 
-	// Now free the section.
-	FreeSection (Section);
+	// Now free the section, or mark it as deleted if we need to keep it for
+	// debugging information purposes.
+#ifdef DEBUGGING_INFO_SUPPORT
+	if (Program->HaveDebuggingInfo)
+		Section->DebuggingInfoType = DI_DELETED;
+	else
+#endif /* DEBUGGING_INFO_SUPPORT */
+		FreeSection (Section);
 }
 
 // Remove all unused sections.
@@ -100,6 +107,10 @@ void RemoveUnusedSections (PROGRAM *Program)
 	
 	for_each (Section, Program->Sections)
 	{
+		// Ignore debugging information sections.
+		if (Section->DebuggingInfoType)
+			continue;
+
 		// If the section is an essential section, mark it (and all sections it
 		// references) as referenced.
 		if (Section->Essential)
@@ -113,6 +124,10 @@ void RemoveUnusedSections (PROGRAM *Program)
 		// has been freed.
 		NextSection = GetNext (Section);
 		
+		// Ignore debugging information sections.
+		if (Section->DebuggingInfoType)
+			continue;
+
 		// Remove the section if it is unused.
 		RemoveSectionIfUnused (Section);
 	}
@@ -134,6 +149,10 @@ void MarkMainSection (PROGRAM *Program)
 	{
 		SYMBOL *Symbol;
 			
+		// Ignore debugging information sections.
+		if (Section->DebuggingInfoType)
+			continue;
+
 		// For each symbol...
 		for_each (Symbol, Section->Symbols)
 		{
@@ -151,7 +170,13 @@ void ResetReferencedFlags (PROGRAM *Program)
 	SECTION *Section;
 
 	for_each (Section, Program->Sections)
+	{
+		// Ignore debugging information sections.
+		if (Section->DebuggingInfoType)
+			continue;
+
 		Section->Referenced = FALSE;
+	}
 }
 
 #endif /* DATA_VAR_SUPPORT */

+ 2 - 0
import/imp_coff.c

@@ -191,6 +191,8 @@ BOOLEAN ImportCOFFFile (PROGRAM *Program, const I1 *File, SIZE FileSize, const c
 					Section->DebuggingInfoType = DI_DEBUG_MACINFO;
 				else if (!strncmp (SectionName, ".debug_p", 8))
 					Section->DebuggingInfoType = DI_DEBUG_PUBNAMES;
+				else if (!strncmp (SectionName, ".debug_r", 8))
+					Section->DebuggingInfoType = DI_DEBUG_RANGES;
 				else if (!strncmp (SectionName, ".debug_s", 8))
 					Section->DebuggingInfoType = DI_DEBUG_STR;
 				else if (!strncmp (SectionName, ".eh_fram", 8))

+ 25 - 5
main.c

@@ -242,20 +242,17 @@ int main (int ArgCount, const char **Args)
 			// sections of each type.
 			{
 				DebuggingInfoTypes i;
-				for (i = 0; i < DI_LAST; i++)
+				for (i = 1; i < DI_LAST; i++)
 				{
 					Program.DebuggingInfoSection[i] = MergeAllSections (&Program, NULL, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, i + 1);
 					if (Program.DebuggingInfoSection[i])
 					{
 						Program.DebuggingInfoSection[i]->Handled = TRUE;
-						// FIXME: How should we remove unused sections with debugging information in place?
-						//        The linker will probably have to understand the debugging information formats up to some point.
-						Program.DebuggingInfoSection[i]->Essential = TRUE;
 						Program.HaveDebuggingInfo = TRUE;
 					}
 				}
 			}
-#endif
+#endif /* DEBUGGING_INFO_SUPPORT */
 
 #ifdef DATA_VAR_SUPPORT
 			// If we want a separate data variable, merge all data
@@ -272,6 +269,16 @@ int main (int ArgCount, const char **Args)
 					// Reset the Referenced flags so we can do another GC pass
 					// when the imports are done.
 					ResetReferencedFlags (&Program);
+
+#ifdef DEBUGGING_INFO_SUPPORT
+					if (Program.HaveDebuggingInfo)
+					{
+						// Merge all unused sections into a .deleted section.
+						Program.DebuggingInfoSection[0] = MergeAllSections (&Program, NULL, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 1);
+						if (Program.DebuggingInfoSection[0])
+							Program.DebuggingInfoSection[0]->Handled = TRUE;
+					}
+#endif /* DEBUGGING_INFO_SUPPORT */
 					
 					DoSpecialDump (1, "(early-cut)");
 				}
@@ -347,6 +354,19 @@ int main (int ArgCount, const char **Args)
 					// Remove unreferenced sections.
 					RemoveUnusedSections (&Program);
 					
+#ifdef DEBUGGING_INFO_SUPPORT
+					if (Program.HaveDebuggingInfo)
+					{
+						// Merge all unused sections into a .deleted section.
+						// Remove the section from early-cutting if we have one.
+						if (Program.DebuggingInfoSection[0])
+							Program.DebuggingInfoSection[0]->Handled = FALSE;
+						Program.DebuggingInfoSection[0] = MergeAllSections (&Program, Program.DebuggingInfoSection[0], TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 1);
+						if (Program.DebuggingInfoSection[0])
+							Program.DebuggingInfoSection[0]->Handled = TRUE;
+					}
+#endif /* DEBUGGING_INFO_SUPPORT */
+
 					DoSpecialDump (4, "(cut)");
 				}