Преглед изворни кода

* workaorund for ld merging problems from Simon Kissel

git-svn-id: trunk@1159 -
florian пре 20 година
родитељ
комит
2476957db9
2 измењених фајлова са 57 додато и 7 уклоњено
  1. 2 3
      utils/fpcres/elfres.pas
  2. 55 4
      utils/fpcres/elfresfix.pas

+ 2 - 3
utils/fpcres/elfres.pas

@@ -467,7 +467,6 @@ begin
   ressym.ptr:=FSectionStream.Position+sizeof(TElf32Header);
   FSymStream.Position:=0;
   FSectionStream.CopyFrom(FSymStream,FSymStream.Size);
-  doalign(4);
 
   // resstr
   resstr.ptr:=FSectionStream.Position+sizeof(TElf32Header);
@@ -555,7 +554,7 @@ begin
   SectionHeader.sh_size:=FSymStream.Size;
   SectionHeader.sh_link:=0;
   SectionHeader.sh_info:=0;
-  SectionHeader.sh_addralign:=4; // alignment
+  SectionHeader.sh_addralign:=1; // DON'T align this, as this section will be merged by ld
   SectionHeader.sh_entsize:=0;
   FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
 
@@ -578,7 +577,7 @@ begin
   SectionHeader.sh_flags:=2; // A
   SectionHeader.sh_addr:=0;
   SectionHeader.sh_offset:=reshash.ptr;
-  SectionHeader.sh_size:=length(ResourceEntries)*sizeof(TELF32ResourceInfo)+4;
+  SectionHeader.sh_size:=length(ResourceEntries)*sizeof(TELF32ResourceInfo);
   SectionHeader.sh_link:=0;
   SectionHeader.sh_info:=0;
   SectionHeader.sh_addralign:=4; // alignment

+ 55 - 4
utils/fpcres/elfresfix.pas

@@ -130,7 +130,6 @@ end;
 { TElf32ResourceFixer }
 
 procedure TElf32ResourceFixer.DoFixStream(Stream: TStream);
-
 var
   ElfHeader:TElf32header;
   ResourceSectionTable: TElf32ResourceSectionTable;
@@ -143,6 +142,19 @@ var
   strtab:string;
   SectionName: string;
   ResPtrsSection: integer;
+  ResHashSection: integer;
+  ResSymSection: integer;
+
+  ResourceInfo: TELF32ResourceInfo;
+  DataIndex, StringIndex: integer;
+  SymString: string;
+
+  procedure DoAlign(var value:integer; const a: integer);
+  var i: integer;
+  begin
+    i:=(4 - (value MOD a)) MOD a;
+    if (i>0) then inc(value,i);
+  end;
 
 begin
   Fixed:=False;
@@ -184,6 +196,7 @@ begin
   end;
 
   ResPtrsSection:=-1;
+  ResHashSection:=-1;
   ResourceSectionTable.version:=66;
 
   // Next cycle through all sections to gather pointers to all the resource
@@ -205,11 +218,13 @@ begin
         end
       else if sn='ressym' then
         begin
+        ResSymSection:=i;
         ResourceSectionTable.ressym.ptr:=SectionHeaders[i].sh_addr;
         ResourceSectionTable.ressym.size:=SectionHeaders[i].sh_size;
         end
       else if sn='reshash' then
         begin
+        ResHashSection:=i;
         ResourceSectionTable.reshash.ptr:=SectionHeaders[i].sh_addr;
         ResourceSectionTable.reshash.size:=SectionHeaders[i].sh_size;
         ResourceSectionTable.resentries:=SectionHeaders[i].sh_size DIV sizeof(TELF32ResourceInfo);
@@ -235,15 +250,51 @@ begin
   // Ok, we now have pointers to all resource sections and also
   // know the number of resources.
   // Now update the resptrs table
-  if ResPtrsSection>-1 then
-    begin
+  if (ResPtrsSection>-1) and (ResHashSection>-1) and (ResSymSection>-1) then
+  begin
     Doverbose(SUpdatingResPtrs);
     Stream.Position:=SectionHeaders[ResPtrsSection].sh_offset;
     Stream.Write(ResourceSectionTable,sizeof(TELF32ResourceSectionTable));
+
+    // LD might have merged the sections of several linked .or together
+    // Therefore our data and stringtable offsets might be messed up and need to recalculated
+
+    // First get the symbol string
+    Stream.Position:=SectionHeaders[ResSymSection].sh_offset;
+    setlength(SymString, SectionHeaders[ResSymSection].sh_size);
+    Stream.Read(SymString[1], SectionHeaders[ResSymSection].sh_size);
+
+    DataIndex:=0;
+    StringIndex:=0;
+    Stream.Position:=SectionHeaders[ResHashSection].sh_offset;
+
+    for i:=0 to ResourceSectionTable.resentries-1 do
+    begin
+      Stream.Position:=SectionHeaders[ResHashSection].sh_offset+i*sizeof(TELF32ResourceInfo);
+      Stream.Read(ResourceInfo, sizeof(TELF32ResourceInfo));
+      ResourceInfo.ptr:=DataIndex;
+      ResourceInfo.name:=StringIndex;
+
+      // advance for next entry
+      DataIndex:=DataIndex+ResourceInfo.size;
+      DoAlign(DataIndex,4); // The data blocks are 32bit aligned
+
+      // find end of current string
+      while SymString[StringIndex+1]<>#0 do
+        inc(StringIndex,1);
+      inc(StringIndex,1);
+      // this should be the start of the next string
+
+      // write back the entry
+      Stream.Position:=SectionHeaders[ResHashSection].sh_offset+i*sizeof(TELF32ResourceInfo);
+      Stream.Write(ResourceInfo, sizeof(TELF32ResourceInfo));
+    end;
     fixed:=true;
-    end
+  end
   else
     DoError(SErrREsptrsNotFound);
+
+
   if fixed then
     DoVerbose(SFileFixed)
   else