<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/88852>88852</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [MIPS] Got `PC offset is too large 0xffffffff....` when linking using LLD
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            lld
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          coder014
      </td>
    </tr>
</table>

<pre>
    When compiling a Rust program to an ELF executable, I encountered the error
```
.....rcgu.o:(.eh_frame): PC offset is too large: 0xffffffff00000968
```
Upon investigation, I found that `lld`, when generating the `.eh_frame_hdr` for DWARF Exception Frame, computes the `pc` as `0xffffffff80020998` and `va` as `0x80020030`. Consequently, `lld` detects an overflow after calculating the offset.
https://github.com/llvm/llvm-project/blob/c13b7485b87909fcf739f62cfa382b55407433c0/lld/ELF/SyntheticSections.cpp#L530-L545

**The program I wrote is a type of kernel code for MIPS32 using static relocation, and I use a linker script to adjust  executable code addresses above `0x80000000`**. Obviously the `pc` obtained by `lld` is incorrect, which overflows the range of a 32-bit integer. Upon reviewing the `getFdePc` code, I found that data reading is based on the **`pointer encoding`** specified in Common Information Entry (CIE). Inspecting the pointer encoding in my object ELF's `cie`, I found it to be **`DW_EH_PE_sdata4`**, causing `lld` to perform **sign extension** when reading the address in FDE.

After further exploration of LLVM MC, I noticed that for MIPS, when not using PIC/PIE, `FDECFIEncoding` is set to `DW_EH_PE_sdata4`,
https://github.com/llvm/llvm-project/blob/c13b7485b87909fcf739f62cfa382b55407433c0/llvm/lib/MC/MCObjectFileInfo.cpp#L338-L352

corroborated by tests.
https://github.com/llvm/llvm-project/blob/c13b7485b87909fcf739f62cfa382b55407433c0/llvm/test/MC/Mips/eh-frame.s#L57-L65

I also attempted linking my object code with `GNU ld`, which did not produce any error messages. It's notable that `GNU ld` imposes additional conditions on overflow checks in `.eh_frame_hdr` generation, not flagging overflow when generating ELF32.
https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=bfd/elf-eh-frame.c;h=902d7c16334ea725b0caac8033d05422316bb4c5;hb=HEAD#l2471
```c
 for (i = 0; i < hdr_info->u.dwarf.fde_count; i++)
        {
          bfd_vma val;

          val = hdr_info->u.dwarf.array[i].initial_loc
            - sec->output_section->vma;
          val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
          if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64
              && (hdr_info->u.dwarf.array[i].initial_loc
                  != sec->output_section->vma + val))
            overflow = true;
```

* Should `lld` add additional checks to avoid such errors? 
* For MIPS32 code using static relocation, why we use `DW_EH_PE_sdata4` to fill `FDECFIEncoding` instead of `DW_EH_PE_udata4`, to store absolute addresses? I don't know if this is specified by MIPS ABI or other specifications. If feasible, could we consider to use `DW_EH_PE_udata4` or `DW_EH_PE_absptr`?
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy8V91u6zYSfhrmZmBDJi1bushF_KPWgM82aLZ7Lg2KHFnskUUtSdnHb78YKlGU07TA9qKCkUiiOPPNzDc_lN6bc4v4yNINS3cPsg-1dY_KanTJYvlQWn1__FpjC8peOtOY9gwSfu19gM7Zs5MXCBZkC_tjAfgdVR9k2SDjWzgAtsr2bUCHGkKNgM5Zx5IdS57YKnn9xcc5XU6d-7ll4onxbI71qXLygoznTDzB8xZsVXkMYDwEa6GR7oy0knyvXq-ErnyVfarht862YNor-mDOMhjbDhgr27eETgZgq6RpNO3gW7iRzWds0clARhN-tkpGXKdaO7ZKoLIOdl-ffi1g_11hR4KhGIBvo8_6gP5td6doi_R0_447SxKe5HkW11pNi1c5_TB-kAgyZg5b23r8b49taO6kY0QNGgOq4Cka9oquauwNZBXQgZKN6pt3QwZXzgfP1CF0Pnq9YLw4m1D35VzZC-NF01zf_s06Z39HFRgvysaWjBdqIcr1MkvLbJ0neaWqtcirFVeVFBkv03SZrJdCqCQK0IwX-yMpeLm3ocZg1Asq8pafq65jXBxTkcyO6TJ9Dd_wl9Pv3zWObDvAzdmARAMJ4d6RMfANXYsNEGtjQL4cnl8Eh96TwT7IYBQ4bKwaA09-PkDvESQ0pv2GDrxypguRzvp3IviEz4NoqbVD79GDLO0Vx-DEK_KG0M7hl_JqbO-b-8e42zJI06KG8j6JmvFgWmWdi84l4hlVjwEcqONke46GShB8VpoApg14RjeHyGuHV4O3CU3PGAqNz1EtQf8D17UMEhxKTZuMh1J61GDbQUC0g3Bb0uNiItOXo43gO1SmMqjBtLC1l4tt4dBW1l2ii2HfBncHxrPtYc94PodDS1tGBv4omcRc7mBL4hhEpqwj-5XB14x8w29ijMoJzN3X0_7n0_P-5Mms5YgypqAcWPDu8GChQ0dQXyVQBQT8HrD1kR3RwJj_bw4ixK_BJ6DFbj-fsvQpJlnVu1CTSd-7xrrBDbaC4_E_X-DLdrCgtcEofI3BG1PHctPa8MrZ58OW8eKZfBczvNjtt8Vh_x4GihlVw2DhTxyw_Qeze5BjaB9ZWnzZ_hIDWZgGiRVvKS5ENjuKlE-dR9S3JTlsyIyAPvh_sjRFOaR1RG86z3iB9SxW-rmP1Wk9O64-1KYDyMZbkCHgpSPwVEcoeO88jlXjZkJNQfrpX7_BpL1QlmujY9A7Z3WvEGR7H5okXNB7eUY_h0OIqdDaoRC9dapRGphLZ2NN0toQ6SQVwna495TSYzNQNapvkcGfdbK3ZjcUSIJVNfJ8JotGCT92xf2xEPzTYHnbO4U36XBu3XmIHq2IomNiV5q2D6bxs7Mu57QiNpJeU_jEpqLbiloGNtVsjINiYlMzscsTrtdqsRJiiXLN0zJRUqosEUIn6ZJzsViV5VKl9HnJxO7n_dOOcdHw5Xrxw2yghueYioxnBpjYQcLEBuh2C7V2J9NWdsbEvp_rm3TVvNJ4inNN_IzxTfzlb9TI2Xoz3gOUlT5dLxKusmFi86G30fJVNlHnZ4qkc_LO0o1h6W5uWhOMbE6NVZPtADPwqGiX7UPXh5Mfuiq9uV7kROVEGeMZ41l84qvJAMV4Dizdw6Sp8Rxm0-cP8kxForCpTthUNUqN0Ysyxi4nCHgyGtvA0s3-cNoen15eWLojDARjfyziq9Xyg0VAqAgY49nfckuUw_iCdPyVc4DxTYwLz6fxIwQj4UlGcD2-G_5xrBzHFHipbd_oSZ-RWn_IySH5aLy4WqPB96oekt0zUcC7oOJ9gIn14y-mmFt9hxvGMebTLkDaKtM0f9JCWh9QampS0939pIeQAB-sQ5Clt00fJkMQoT6AJiTrAN9aeyNChJoGGj8ZEMp7NAeeNgewDmxskq_LgylU5SqoUHrzenZQ0Zc3mrtab4hXwf7BzBEoiZ0uyNJ3gWoaE8WDfhQ6F7l8wMfFeiF4ukwXi4f6UUu9TjVf8IqvVbLCHCtRCpGLVZmuVnz9YB55wpfJcrFKsmSRLua6Ulm1SLNcpVkl84QtE7xI08yph1CVezDe9_iYZVnKHxpZYuPjuYrzOABzOmC5x9iyyv7s2TJpDDW7cX8woYlHsTgWpDv4ycZi__npZ5K5dHwiR8T6_NaHBuIcj7uH3jWP_3cvjcZQI4z2_C8AAP__Q8Zi9w">