gcunused.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /* gcunused.c: Routines to remove unused sections
  2. Copyright (C) 2002-2004 Sebastian Reichelt
  3. Copyright (C) 2003-2005 Kevin Kofler
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software Foundation,
  14. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  15. #include "gcunused.h"
  16. #include <string.h>
  17. #include "manip.h"
  18. #include "special.h"
  19. // Recursively mark the target section of the specified location, if any (i.e.
  20. // if the location is non-NULL), as referenced.
  21. #define MarkLocation(Location) \
  22. if ((Location) && (Location)->Symbol) \
  23. MarkSection ((Location)->Symbol->Parent)
  24. // Mark a section as referenced. If it was not already marked, follow all relocs
  25. // from this section and recursively mark the target sections of all the relocs.
  26. static void MarkSection (SECTION *Section)
  27. {
  28. RELOC *Reloc;
  29. // If the section is already marked, or if it is a debugging information
  30. // section, return immediately.
  31. if (Section->Referenced || Section->DebuggingInfoType)
  32. return;
  33. // Mark the section right now to avoid infinite recursion.
  34. Section->Referenced = TRUE;
  35. // Recursively mark the target section and the relation section of all
  36. // relocs in this section
  37. for_each (Reloc, Section->Relocs)
  38. {
  39. MarkLocation (&(Reloc->Target));
  40. MarkLocation (Reloc->Relation);
  41. }
  42. }
  43. // Free a section if it is no longer referenced. Update the ReferencedLibCount
  44. // accordingly.
  45. static void RemoveSectionIfUnused (SECTION *Section)
  46. {
  47. PROGRAM *Program = Section->Parent;
  48. SECTION *OtherSection;
  49. LIB_CALL *LibCall, *OtherSecLibCall;
  50. // Don't free the section if it is still referenced.
  51. if (Section->Referenced)
  52. return;
  53. // If this section references any libraries, and if it was the last one to
  54. // reference them, we need to mark the library as no longer referenced.
  55. for_each (LibCall, Section->LibCalls)
  56. {
  57. LIBRARY *Library = LibCall->Library;
  58. if (Library->Referenced)
  59. {
  60. for_each (OtherSection, Program->Sections)
  61. {
  62. // Not this section!
  63. if (OtherSection == Section) continue;
  64. for_each (OtherSecLibCall, OtherSection->LibCalls)
  65. {
  66. // If this library is still referenced, forget it.
  67. if (OtherSecLibCall->Library == Library) goto NextLibCall;
  68. }
  69. }
  70. // The library is no longer referenced after this section is removed.
  71. Library->Referenced = FALSE;
  72. Program->Libraries.ReferencedCount--;
  73. }
  74. NextLibCall:;
  75. }
  76. // Now free the section, or mark it as deleted if we need to keep it for
  77. // debugging information purposes.
  78. #ifdef DEBUGGING_INFO_SUPPORT
  79. if (Program->HaveDebuggingInfo)
  80. Section->DebuggingInfoType = DI_DELETED;
  81. else
  82. #endif /* DEBUGGING_INFO_SUPPORT */
  83. FreeSection (Section);
  84. }
  85. // Remove all unused sections.
  86. void RemoveUnusedSections (PROGRAM *Program)
  87. {
  88. SECTION *Section, *NextSection;
  89. for_each (Section, Program->Sections)
  90. {
  91. // Ignore debugging information sections.
  92. if (Section->DebuggingInfoType)
  93. continue;
  94. // If the section is an essential section, mark it (and all sections it
  95. // references) as referenced.
  96. if (Section->Essential)
  97. MarkSection (Section);
  98. }
  99. // For each section...
  100. for (Section = GetFirst (Program->Sections); Section; Section = NextSection)
  101. {
  102. // Get the next section now, since GetNext won't work once the section
  103. // has been freed.
  104. NextSection = GetNext (Section);
  105. // Ignore debugging information sections.
  106. if (Section->DebuggingInfoType)
  107. continue;
  108. // Remove the section if it is unused.
  109. RemoveSectionIfUnused (Section);
  110. }
  111. }
  112. // The following 2 functions are currently needed only for external data
  113. // variable support.
  114. #ifdef DATA_VAR_SUPPORT
  115. // Mark the section containing __main as Referenced. This is a kludge
  116. // compensating for the fact that the startup section referencing __main has not
  117. // been imported at that stage.
  118. void MarkMainSection (PROGRAM *Program)
  119. {
  120. SECTION *Section;
  121. // For each section...
  122. for_each (Section, Program->Sections)
  123. {
  124. SYMBOL *Symbol;
  125. // Ignore debugging information sections.
  126. if (Section->DebuggingInfoType)
  127. continue;
  128. // For each symbol...
  129. for_each (Symbol, Section->Symbols)
  130. {
  131. // If the name matches, we have found the right symbol.
  132. if (Symbol->Exported && (!(strcmp ("__main", Symbol->Name))))
  133. MarkSection (Section);
  134. }
  135. }
  136. }
  137. // Clear the Referenced flag of all sections, in order to be able to run a
  138. // second RemoveUnusedSections pass at a later point.
  139. void ResetReferencedFlags (PROGRAM *Program)
  140. {
  141. SECTION *Section;
  142. for_each (Section, Program->Sections)
  143. {
  144. // Ignore debugging information sections.
  145. if (Section->DebuggingInfoType)
  146. continue;
  147. Section->Referenced = FALSE;
  148. }
  149. }
  150. #endif /* DATA_VAR_SUPPORT */