---
# System prepended metadata

title: 'Binutils: Adding LD Parameters'

---

# Binutils: Adding LD Parameters for RISC-V


This artical is about how to add ld parameters in binutils.




## Related Files

* *ld/emultempl/elf.em*: this is the general template of the emitted C file
* *ld/emultempl/riscvelf.em*: RISC-V specific script to emit C file

**NOTE** The em means "emit" (maybe ...)


## ld/emultempl/elf.em

*ld/emultempl/elf.em* is the top level of emit template. It reads the content of other *.em* fils and emit the final C file.


## ld/emultempl/riscvelf.em

If we build binutils for RISC-V target, *<build_dir>/ld/eelf\*briscv.c* files are generated from this script.

In `riscvelf.em`, one can use some syntax to specify what to emit.


### Inserting lines to the emitted C file

``` shell
fragment <<EOF
...
<content you want to add to the emitted C file.
...
EOF
```

This is known as the ["here-document"](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04) syntax, that "redirection of subsequent lines read by the shell to the input of a command".

:::info
ℹ️ **NOTE**
The `fragment()` command is defined in *ld/genscrba.sh*:

```
fragment()
{
  if [ ${BASH_VERSINFO[3]} -ge 3 ]; then
    local lineno=$[${BASH_LINENO[0]} + 1]
    echo >> e${EMULATION_NAME}.c "#line $lineno \"$em_script\""
  fi
  cat >> e${EMULATION_NAME}.c
}
```
:::



### Predefined shell variables

To add a new option, we need to set several shell variables in the *.em* file.

* `$PARSE_AND_LIST_PROLOGUE`: defines enums that will be refer to this option.
* `$PARSE_AND_LIST_LONGOPTS`: defines the ld option properties, like option name, type, and enum refering to the options.
* `$PARSE_AND_LIST_OPTIONS`: a small piece of C code that prints the option help message.
* `$PARSE_AND_LIST_ARGS_CASES`: a small piece of `case` condition to set variables to store pares result.


## Example: Adding `--relax-gp` Option

Here is the reference commit:
https://github.com/bminor/binutils-gdb/commit/50980ba351856dff75bb0743bfca62f4c3ab19ff


At the beginning, of *riscvelf.em*, it inserts some include statement and defined some variables:

``` c
fragment <<EOF

#include "ldmain.h"
#include "ldctor.h"
#include "elf/riscv.h"
#include "elfxx-riscv.h"

static struct riscv_elf_params params = { .relax_gp = 1 };
EOF
```


Note that the `riscv_elf_params` is defined in *struct elfxx-riscv.h*.


Then it defines the shell script variables we mentioned above.

`$PARSE_AND_LIST_PROLOGUE` to add new enum:

```
# Define some shell vars to insert bits of code into the standard elf
# parse_args and list_options functions.  */
PARSE_AND_LIST_PROLOGUE=${PARSE_AND_LIST_PROLOGUE}'
enum risccv_opt
{
  OPTION_RELAX_GP = 321,
  OPTION_NO_RELAX_GP,
};
'
```

`$PARSE_AND_LIST_LONGOPTS` to set parameter properties:
```
PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
    { "relax-gp", no_argument, NULL, OPTION_RELAX_GP },
    { "no-relax-gp", no_argument, NULL, OPTION_NO_RELAX_GP },
'
```

`$PARSE_AND_LIST_OPTIONS` to print help message:
```
PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'
  fprintf (file, _("  --relax-gp                  Perform GP relaxation\n"));
  fprintf (file, _("  --no-relax-gp               Don'\''t perform GP relaxation\n"));
'
```

`$PARSE_AND_LIST_ARGS_CASES` to add new switch-case for option parser:
```
PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
    case OPTION_RELAX_GP:
      params.relax_gp = 1;
      break;

    case OPTION_NO_RELAX_GP:
      params.relax_gp = 0;
      break;
'
```