gcunused.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* gcunused.c: Routines to remove unused sections
  2. Copyright (C) 2002-2004 Sebastian Reichelt
  3. Copyright (C) 2003-2008 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 <stdlib.h>
  17. #include <string.h>
  18. #include "manip.h"
  19. #include "special.h"
  20. // Recursively mark the target section of the specified location, if any (i.e.
  21. // if the location is non-NULL), as referenced.
  22. #define MarkLocation(Location) \
  23. if ((Location) && (Location)->Symbol) \
  24. MarkSection ((Location)->Symbol->Parent)
  25. // Mark a section as referenced. If it was not already marked, follow all relocs
  26. // from this section and recursively mark the target sections of all the relocs.
  27. static void MarkSection (SECTION *Section)
  28. {
  29. RELOC *Reloc;
  30. // If the section is already marked, or if it is a debugging information
  31. // section, return immediately.
  32. if (Section->Referenced || Section->DebuggingInfoType)
  33. return;
  34. // Mark the section right now to avoid infinite recursion.
  35. Section->Referenced = TRUE;
  36. // Recursively mark the target section and the relation section of all
  37. // relocs in this section
  38. for_each (Reloc, Section->Relocs)
  39. {
  40. MarkLocation (&(Reloc->Target));
  41. MarkLocation (Reloc->Relation);
  42. }
  43. }
  44. // Free a section if it is no longer referenced. Update the ReferencedLibCount
  45. // accordingly.
  46. static void RemoveSectionIfUnused (SECTION *Section)
  47. {
  48. PROGRAM *Program = Section->Parent;
  49. SECTION *OtherSection;
  50. LIB_CALL *LibCall, *OtherSecLibCall;
  51. // Don't free the section if it is still referenced.
  52. if (Section->Referenced)
  53. return;
  54. // If this section references any libraries, and if it was the last one to
  55. // reference them, we need to mark the library as no longer referenced.
  56. for_each (LibCall, Section->LibCalls)
  57. {
  58. LIBRARY *Library = LibCall->Library;
  59. if (Library->Referenced)
  60. {
  61. for_each (OtherSection, Program->Sections)
  62. {
  63. // Not this section!
  64. if (OtherSection == Section) continue;
  65. for_each (OtherSecLibCall, OtherSection->LibCalls)
  66. {
  67. // If this library is still referenced, forget it.
  68. if (OtherSecLibCall->Library == Library) goto NextLibCall;
  69. }
  70. }
  71. // The library is no longer referenced after this section is removed.
  72. Library->Referenced = FALSE;
  73. Program->Libraries.ReferencedCount--;
  74. }
  75. NextLibCall:;
  76. }
  77. // Now free the section, or mark it as deleted if we need to keep it for
  78. // debugging information purposes.
  79. #ifdef DEBUGGING_INFO_SUPPORT
  80. if (Program->HaveDebuggingInfo)
  81. {
  82. Section->DebuggingInfoType = DI_DELETED;
  83. // Remove all ROM_CALLs, RAM_CALLs and library calls from the
  84. // deleted section. GDB can't handle them anyway and they cause
  85. // invalid entries in the relocation table.
  86. #define FreeItems(Type,Item) \
  87. ({ \
  88. Type *Item, *Next##Item; \
  89. for (Item = GetLast (Section->Item##s); Item; Item = Next##Item) \
  90. { \
  91. Next##Item = GetPrev (Item); \
  92. free (Item); \
  93. } \
  94. GetFirst (Section->Item##s) = GetLast (Section->Item##s) = NULL; \
  95. })
  96. FreeItems (LIB_CALL, LibCall);
  97. FreeItems (RAM_CALL, RAMCall);
  98. FreeItems (ROM_CALL, ROMCall);
  99. #undef FreeItems
  100. }
  101. else
  102. #endif /* DEBUGGING_INFO_SUPPORT */
  103. FreeSection (Section);
  104. }
  105. // Remove all unused sections.
  106. void RemoveUnusedSections (PROGRAM *Program)
  107. {
  108. SECTION *Section, *NextSection;
  109. for_each (Section, Program->Sections)
  110. {
  111. // Ignore debugging information sections.
  112. if (Section->DebuggingInfoType)
  113. continue;
  114. // If the section is an essential section, mark it (and all sections it
  115. // references) as referenced.
  116. if (Section->Essential)
  117. MarkSection (Section);
  118. }
  119. // For each section...
  120. for (Section = GetFirst (Program->Sections); Section; Section = NextSection)
  121. {
  122. // Get the next section now, since GetNext won't work once the section
  123. // has been freed.
  124. NextSection = GetNext (Section);
  125. // Ignore debugging information sections.
  126. if (Section->DebuggingInfoType)
  127. continue;
  128. // Remove the section if it is unused.
  129. RemoveSectionIfUnused (Section);
  130. }
  131. }
  132. // The following 2 functions are currently needed only for external data
  133. // variable support.
  134. #ifdef DATA_VAR_SUPPORT
  135. // Mark the section containing __main as Referenced. This is a kludge
  136. // compensating for the fact that the startup section referencing __main has not
  137. // been imported at that stage.
  138. void MarkMainSection (PROGRAM *Program)
  139. {
  140. SECTION *Section;
  141. // For each section...
  142. for_each (Section, Program->Sections)
  143. {
  144. SYMBOL *Symbol;
  145. // Ignore debugging information sections.
  146. if (Section->DebuggingInfoType)
  147. continue;
  148. // For each symbol...
  149. for_each (Symbol, Section->Symbols)
  150. {
  151. // If the name matches, we have found the right symbol.
  152. if (Symbol->Exported && (!(strcmp ("__main", Symbol->Name))))
  153. MarkSection (Section);
  154. }
  155. }
  156. }
  157. // Clear the Referenced flag of all sections, in order to be able to run a
  158. // second RemoveUnusedSections pass at a later point.
  159. void ResetReferencedFlags (PROGRAM *Program)
  160. {
  161. SECTION *Section;
  162. for_each (Section, Program->Sections)
  163. {
  164. // Ignore debugging information sections.
  165. if (Section->DebuggingInfoType)
  166. continue;
  167. Section->Referenced = FALSE;
  168. }
  169. }
  170. #endif /* DATA_VAR_SUPPORT */