Skip to content

Commit

Permalink
vault backup: 2023-11-03 13:32:28
Browse files Browse the repository at this point in the history
Affected files:
content/2023-11-03.md
  • Loading branch information
pietraferreira committed Nov 3, 2023
1 parent 2d84135 commit 281bc8d
Showing 1 changed file with 79 additions and 83 deletions.
162 changes: 79 additions & 83 deletions content/2023-11-03.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,37 @@
# Relocation Prototype Synch-up
---
## Reasoning
- For example, in CORE-V, we have custom relocation that live in the reserved space, but we need to be able to share that reserved space with other toolchains (as even though the space is quite large, it is finite).
- We need a better way of using this space, for else having someone else occupy the same space and have tools like the linker process the correct version of that relocation number.

Vendor specific relocations resides in reserved space. However, this space must be shared with other toolchains due to its finite space. It is imperative to find a more efficient way to utilise this space, ensuring that different toolchains can process the appropriate versions of a relocation number.
## Approach
- Use a second relocation at the same address, which will be used to decide how to interpret that relocation.
To address this challenge, a second relocation at the same memory address is introduced. This secondary relocation is used to determine how to interpret the primary relocation. We accomplish this by creating a new relocation type called `BFD_RELOC_RISCV_RELOCID`. CORE-V relocations are assigned a unique ID (0x100).

- In practice: we have a relocation called `relocid` which should accompany all vendor specific relocations: `BFD_RELOC_RISCV_RELOCID`. I created a boolean called `corev_identifier` to flag relocations as CORE-V relocations. We give the CORE-V vendor specific relocations an ID number (0x100):
Here's a code snippet illustrating this concept:

```c
/* CORE-V Specific. */
case BFD_RELOC_RISCV_CVPCREL_UI12:
...
/* Add a R_RISCV_RELOCID reloc to specify vendor. */
/* We check if it is a COREV relocation, if so the ID value is 0x100. */
if (corev_identifier && fixP->fx_tcbit && fixP->fx_addsy != NULL)
{
fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
fixP->fx_next->fx_addsy = fixP->fx_next->fx_subsy = NULL;
fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_RELOCID;
fixP->fx_next->fx_size = 0;
/* ID */
/* Set the ID value to 0x100 */
fixP->fx_next->fx_offset = 0x100;
}
```
Now `BFD_RELOC_RISCV_CVPCREL_UI12` has set `relocID` as an accompanying relocation and has set its ID value as `0x100`.
Now `BFD_RELOC_RISCV_CVPCREL_UI12` is associated with `R_RISCV_RELOCID`, and its ID is set to `0x100`.
In `perform_relocation` (`elfnn-riscv.c`), we created a variable to hold the next relocation:
In the `perform_relocation` function (`elfnn-riscv.c`), we introduce a variable to hold the next relocation type:
```c
int next_reloc = ELFNN_R_TYPE ((rel + 1)->r_info);
```

Then in `R_RISCV_CVPCREL_UI12` (`elfnn-riscv.c`) we check its accompanying relocation and its value (ID):
We then check the accompanying relocation and its value (ID) in `R_RISCV_CVPCREL_UI12` (`elfnn-riscv.c`):

```c
case R_RISCV_CVPCREL_UI12:
Expand All @@ -46,7 +43,7 @@ case R_RISCV_CVPCREL_UI12:
}
```
In case of `0x100`:
In the case of `0x100`, we handle it as follows:
```c
switch ((rel + 1)->r_addend)
Expand All @@ -60,54 +57,10 @@ In case of `0x100`:
break;
```

## Challenges and Next Steps
The main challenge in this project is handling the `howto` table.

An alternative implementation, was to have this logic under `relocID`, but that wouldn't scale well:

```c
/* Relocation handling prototype */
case R_RISCV_RELOCID:
switch (value) {
case 100:
// here howto retrieves the previous relocation
howto = riscv_elf_rtype_to_howto (input_bfd, prev_reloc_type);
// trying to hardcode the value to see if the logic works
value = 6;
value = ENCODE_ITYPE_IMM (value >> howto->rightshift);
break;
}
break;
```
When it comes to bugs, the main issue I am having is achieving the correct behaviour.
The output looks like this:
```bash
❯ ../../../install/bin/riscv32-corev-elf-as -march=rv32imc_xcorevhwlp1p0 -o test-1606-1616-pf.o test-addi.s
❯ ../../../install/bin/riscv32-corev-elf-objdump -dr test-1606-1616-pf.o
test-1606-1616-pf.o: file format elf32-littleriscv
Disassembly of section .text:
00000000 <func>:
0: 8082 ret
00000002 <_start>:
2: 0060007b cv.starti 0,e <L2>
2: R_RISCV_CVPCREL_UI12 L2
2: R_RISCV_RELOCID *ABS*+0x100
6: 00000097 auipc ra,0x0
6: R_RISCV_CALL func
6: R_RISCV_RELAX *ABS*
a: 000080e7 jalr ra # 6 <_start+0x4>
0000000e <L2>:
e: 0001 nop
```

My proof of idea is the relaxation implementation, which looks something like this:
The key aspect of this prototype is the relaxation implementation. The relaxation function is based on the relocation type, such as `R_RISCV_CALL` or `R_RISCV_HI20`:

```c
if (type == R_RISCV_CALL
Expand All @@ -125,9 +78,47 @@ if (type == R_RISCV_CALL
else
```

Another idea that I tried for a while, was to have a secondary table where the `special_function` is `riscv_elf_custom_relocid`, which should then trigger `perform_relocation`. This means instead of having the identification mechanism in `perform_relocation` itself, like I previously explained, we would have it in a separate function. However, I didn't get very far on this as I wasn't sure on how to handle a second howto table and the first approach was more intuitive for a prototype. However, this might be a more solid approach as we would be keeping the logic modular.
The next step involves exploring the `howto` table entry for the set ID, but there is a limitation in writing additional `howto` table entries as the IDs overlap with existing ones. To address this, a secondary `howto` table has been introduced.

This is how the function looks like:
```c
/* Prototype not currently being used, relates to RELOCID */
static reloc_howto_type SECONDARYhowto_table[] = {
/* CORE-V Specific. */
/* 12-bit PC-relative offset, for hwloop. */
HOWTO (R_RISCV_CVPCREL_UI12, /* type */
1, /* rightshift */
2, /* size */
32, /* bitsize */
true, /* pc_relative */
0, /* bitpos */
complain_overflow_unsigned, /* complain_on_overflow */
//riscv_elf_custom_relocid, /* special_function */
bfd_elf_generic_reloc, /* special_function */
"R_RISCV_CVPCREL_UI12", /* name */
false, /* partial_inplace */
0, /* src_mask */
ENCODE_ITYPE_IMM (-1U), /* dst_mask */
true), /* pcrel_offset */

HOWTO (R_RISCV_RELOCID, /* type */
0, /* rightshift */
3, /* size */
32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_RISCV_RELOCID", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
};
```

The `special_function` here is `riscv_elf_custom_relocid`, which is expected to trigger the `perform_relocation` function. However, the integration of this logic is still a work in progress.

This is how the function currently looks like:

```c
static bfd_reloc_status_type
Expand Down Expand Up @@ -172,28 +163,6 @@ riscv_elf_custom_relocid (bfd *abfd,
}
```
And in `elfnn-riscv.c` we would have this instead:
```c
/* Relocation handling prototype */
case R_RISCV_RELOCID:
switch (value) {
case 100:
// ;
return riscv_elf_custom_relocid(ELFNN_R_TYPE (rel->r_info));
//return get_howto_from_table(&SECONDARYhowto_table, rel);
//return bfd_reloc_ok;
}
break;
```

But as I mentioned previously, I didn't get farther than this.

## Repos
- binutils: https://github.com/pietraferreira/corev-binutils-gdb.git (pf-relocation-dev-wip)
- gcc: openhw/development
- gdb: openhw/development
- newlib: newlib-4.1.0 (newlib-cygwin)
## Commands
- Test case:
Expand All @@ -220,6 +189,33 @@ riscv32-corev-elf-as -march=rv32imc_xcorevhwlp1p0 -o test.o test.s
riscv32-corev-elf-objdump -dr test.o
```

- The output looks like this:

```bash
❯ ../../../install/bin/riscv32-corev-elf-as -march=rv32imc_xcorevhwlp1p0 -o test-1606-1616-pf.o test-addi.s
❯ ../../../install/bin/riscv32-corev-elf-objdump -dr test-1606-1616-pf.o

test-1606-1616-pf.o: file format elf32-littleriscv


Disassembly of section .text:

00000000 <func>:
0: 8082 ret

00000002 <_start>:
2: 0060007b cv.starti 0,e <L2>
2: R_RISCV_CVPCREL_UI12 L2
2: R_RISCV_RELOCID *ABS*+0x100
6: 00000097 auipc ra,0x0
6: R_RISCV_CALL func
6: R_RISCV_RELAX *ABS*
a: 000080e7 jalr ra # 6 <_start+0x4>

0000000e <L2>:
e: 0001 nop
```

- To debug:

You first run:
Expand All @@ -240,7 +236,7 @@ And run it like this:
gdb --args ~/corev/build/binutils-gdb/ld/ld-new -plugin /home/pietraferreira/corev/install/libexec/gcc/riscv32-corev-elf/12.0.0/liblto_plugin.so -plugin-opt=/home/pietraferreira/corev/install/libexec/gcc/riscv32-corev-elf/12.0.0/lto-wrapper -plugin-opt=-fresolution=test.o.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgloss -plugin-opt=-pass-through=-lgcc --sysroot=/home/pietraferreira/corev/install/riscv32-corev-elf -melf32lriscv -o test.o -L/home/pietraferreira/corev/install/lib/gcc/riscv32-corev-elf/12.0.0 -L/home/pietraferreira/corev/install/lib/gcc/riscv32-corev-elf/12.0.0/../../../../riscv32-corev-elf/lib -L/home/pietraferreira/corev/install/riscv32-corev-elf/lib test.o -lgcc --start-group -lc -lgloss --end-group -lgcc
```

Finally, you will probably need to add missing directories to GDB, this can be done like this:
Additionally, you might need to add missing directories to GDB with this command:

```bash
# in GDB:
Expand Down

0 comments on commit 281bc8d

Please sign in to comment.