Symbian
Symbian OS Library

FAQ-0683 How do I debug "Bad relocation" error in PETRAN?

[Index][spacer] [Previous] [Next]



 

Classification: C++ Category: Debugging
Created: 10/10/2000 Modified: 03/07/2005
Number: FAQ-0683
Platform: Symbian OS v6.0, Symbian OS v6.1, Symbian OS v7.0, Symbian OS v7.0s, Symbian OS v8.0, Symbian OS v8.0a, Symbian OS v8.0b, Symbian OS v8.1a, Symbian OS v8.1b

Question:
When I try to build my DLL for ARM, PETRAN fails and reports "ERROR: bad relocation". What does it mean and what can I
do to fix it?


Answer:
The problem arises when PETRAN attempts to reorganise the PE-COFF executable: the "bad relocation" is a reference in the code to an address which doesn't reside in any of the code or data areas, so PETRAN does not know how to adjust it.

Here's an example:
    ERROR: bad relocation: [000013dc] = d2002854
    WARNING: Address to relocate does not point at .text, .rdata, .idata or data sections
    WARNING: Problem address = e20028548 (section -1)

    ERROR: bad relocation: [0000145c] = d2002854
    WARNING: Address to relocate does not point at .text, .rdata, .idata or data sections
    WARNING: Problem address = e20028548 (section -1)
    The WARNING lines are really just repeating the ERROR information without adding anything extra (and that "problem address" is printed with a spurious 8 on the end!).

    The number in [square brackets] is an offset in the PE-COFF file, and can be looked up in the corresponding .MAP file. The .text section starts at address 0x10000000 by default, so we need to look in the .MAP file for the part of the text section which contains 0x100013dc

    .text 0x100010b4 0x760 ..\..\EPOC32\BUILD\UIKLAF\GROUP\UIKLAF\ARMI\UREL\UIKLAF.in(LAFAKNBORDERS.o)
    0x100010b4 LafAknBorders::DrawLogicalBorder(TGulBorder const &, CGraphicsContext &, TRect const &, TGulBorder::TColors const &)
    0x100013ec LafAknBorders::LogicalBorderMargins(TGulBorder const &)
    0x1000146c SBorderBit::Draw(CGraphicsContext &, TRect const &) const
    0x10001550 SBorderBit::DrawSide(CGraphicsContext &, TRect const &, int) const
    0x100016c8 SBorderBit::Rect(TRect const &) const
    0x10001728 SBorderSpec::Draw(CGraphicsContext &, TRect const &) const
    0x10001778 SBorderSpec::ClearMargins(CGraphicsContext &, TRect const &) const

    The map information is not in address order, but both of the problem offsets (13dc and 145c) lie within 0x760 bytes from 0x100010b4. This means that the problematic relocations are somewhere in the LAFAKNBORDERS.CPP file.

    The next step is to obtain an assembler listing for that file, which is most easily done using the "ABLD LISTING" command., in this case
      abld listing armi urel uiklaf lafaknborders
      This produces lafaknborders.lis in the same directory as the source file. The listing file shows the code offsets numbered from 0, so we need to look at offset (0x100013cd - 0x10010b4) = 0x328 for the first defect, and offset 0x3a8 for the second.
        328: d1ff9e40 mvnles r9, r0, asr #28
        328: ARM_32 gBorderSpecs

        3a8: d1ff9e40 mvnles r9, r0, asr #28
        3a8: ARM_32 gBorderSpecs
        In both cases this is an address related to something called "gBorderSpecs" - the number 0xd1ff9e40 isn't an instruction and can be ignored.


        That's very interesting, but what can I do about it?

        The problem usually arises from a compiler optimisation. If you have code which looks something like
          x = lookup_table [p-'a'];
          then the compiler will realise that it can convert this into
            x = *(lookup_table - 'a')+p;
            and take advantage of the fact that (lookup_table-'a') is a constant. Unfortunately, the way our toolchain works doesn't quite cope with the situation where lookup_table is close to the start of the data section, in which case you get the confusing error messages of the type you've seen.

            The usual fix is to do the sums separately from the array reference and hope that the compiler can't get a clear enough picture of what's happening to reapply the optimisation. If that fails you can try moving the array around.