# 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;
'
```