Browse Source

Fixed bug in ARM coff writer. Relocations just ORed the offset onto the instruction instead of adding, but they are emitted as bl 0xFFFFFE, and not bl 0x0.

git-svn-id: trunk@30403 -
Jeppe Johansen 10 years ago
parent
commit
a3fd3ee3ab
1 changed files with 9 additions and 4 deletions
  1. 9 4
      compiler/ogcoff.pas

+ 9 - 4
compiler/ogcoff.pas

@@ -835,6 +835,9 @@ const pemagic : array[0..3] of byte = (
         objreloc : TObjRelocation;
         objreloc : TObjRelocation;
         address,
         address,
         relocval : aint;
         relocval : aint;
+{$ifdef arm}
+        addend   : aint;
+{$endif arm}
         relocsec : TObjSection;
         relocsec : TObjSection;
 {$ifdef cpu64bitaddr}
 {$ifdef cpu64bitaddr}
         s        : string;
         s        : string;
@@ -912,16 +915,18 @@ const pemagic : array[0..3] of byte = (
 {$ifdef arm}
 {$ifdef arm}
                 RELOC_RELATIVE_24:
                 RELOC_RELATIVE_24:
                   begin
                   begin
-                    relocval:=longint(relocval - objsec.mempos - objreloc.dataoffset) shr 2 - 2;
-                    address:=address or (relocval and $ffffff);
+                    addend:=sarlongint(((address and $ffffff) shl 8),8);
+                    relocval:=longint(relocval - objsec.mempos - objreloc.dataoffset + addend) shr 2;
+                    address:=(address and $ff000000) or (relocval and $ffffff);
                     relocval:=relocval shr 24;
                     relocval:=relocval shr 24;
                     if (relocval<>$3f) and (relocval<>0) then
                     if (relocval<>$3f) and (relocval<>0) then
                       internalerror(200606085);  { offset overflow }
                       internalerror(200606085);  { offset overflow }
                   end;
                   end;
                 RELOC_RELATIVE_24_THUMB:
                 RELOC_RELATIVE_24_THUMB:
                   begin
                   begin
-                    relocval:=longint(relocval - objsec.mempos - objreloc.dataoffset) shr 1 - 4;
-                    address:=address or ((relocval shr 1) and $ffffff) or ((relocval and 1) shl 24);
+                    addend:=sarlongint(((address and $ffffff) shl 8),8);
+                    relocval:=longint(relocval - objsec.mempos - objreloc.dataoffset + addend) shr 1;
+                    address:=(address and $ff000000) or ((relocval shr 1) and $ffffff) or ((relocval and 1) shl 24);
                     relocval:=relocval shr 25;
                     relocval:=relocval shr 25;
                     if (relocval<>$3f) and (relocval<>0) then
                     if (relocval<>$3f) and (relocval<>0) then
                       internalerror(200606085);  { offset overflow }
                       internalerror(200606085);  { offset overflow }