33
33
#include "opcode/riscv.h"
34
34
#include "objalloc.h"
35
35
36
+ #ifdef HAVE_LIMITS_H
37
+ #include <limits.h>
38
+ #endif
39
+ #ifndef CHAR_BIT
40
+ #define CHAR_BIT 8
41
+ #endif
42
+
36
43
/* Internal relocations used exclusively by the relaxation pass. */
37
44
#define R_RISCV_DELETE (R_RISCV_max + 1)
38
45
@@ -125,6 +132,18 @@ struct riscv_elf_link_hash_table
125
132
bfd_vma last_iplt_index ;
126
133
};
127
134
135
+ /* Instruction access functions. */
136
+
137
+ #define riscv_get_insn (bits , ptr ) \
138
+ ((bits) == 16 ? bfd_getl16 (ptr) \
139
+ : (bits) == 32 ? bfd_getl32 (ptr) \
140
+ : (bits) == 64 ? bfd_getl64 (ptr) \
141
+ : (abort (), (bfd_vma) - 1))
142
+ #define riscv_put_insn (bits , val , ptr ) \
143
+ ((bits) == 16 ? bfd_putl16 (val, ptr) \
144
+ : (bits) == 32 ? bfd_putl32 (val, ptr) \
145
+ : (bits) == 64 ? bfd_putl64 (val, ptr) \
146
+ : (abort (), (void) 0))
128
147
129
148
/* Get the RISC-V ELF linker hash table from a link_info structure. */
130
149
#define riscv_elf_hash_table (p ) \
@@ -152,6 +171,19 @@ riscv_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
152
171
bed -> s -> swap_reloca_out (abfd , rel , loc );
153
172
}
154
173
174
+ /* Return true if a relocation is modifying an instruction. */
175
+
176
+ static bfd_boolean
177
+ riscv_is_insn_reloc (const reloc_howto_type * howto )
178
+ {
179
+ /* Heuristic: A multibyte destination with a nontrivial mask
180
+ is an instruction */
181
+ return (howto -> bitsize > 8
182
+ && howto -> dst_mask != 0
183
+ && ~(howto -> dst_mask | (howto -> bitsize < sizeof (bfd_vma ) * CHAR_BIT
184
+ ? (MINUS_ONE << howto -> bitsize ) : (bfd_vma )0 )) != 0 );
185
+ }
186
+
155
187
/* PLT/GOT stuff. */
156
188
157
189
#define PLT_HEADER_INSNS 8
@@ -1645,10 +1677,10 @@ perform_relocation (const reloc_howto_type *howto,
1645
1677
/* Linker relaxation can convert an address equal to or greater than
1646
1678
0x800 to slightly below 0x800. C.LUI does not accept zero as a
1647
1679
valid immediate. We can fix this by converting it to a C.LI. */
1648
- bfd_vma insn = bfd_get (howto -> bitsize , input_bfd ,
1649
- contents + rel -> r_offset );
1680
+ bfd_vma insn = riscv_get_insn (howto -> bitsize ,
1681
+ contents + rel -> r_offset );
1650
1682
insn = (insn & ~MATCH_C_LUI ) | MATCH_C_LI ;
1651
- bfd_put (howto -> bitsize , input_bfd , insn , contents + rel -> r_offset );
1683
+ riscv_put_insn (howto -> bitsize , insn , contents + rel -> r_offset );
1652
1684
value = ENCODE_RVC_IMM (0 );
1653
1685
}
1654
1686
else if (!VALID_RVC_LUI_IMM (RISCV_CONST_HIGH_PART (value )))
@@ -1684,9 +1716,16 @@ perform_relocation (const reloc_howto_type *howto,
1684
1716
return bfd_reloc_notsupported ;
1685
1717
}
1686
1718
1687
- bfd_vma word = bfd_get (howto -> bitsize , input_bfd , contents + rel -> r_offset );
1719
+ bfd_vma word ;
1720
+ if (riscv_is_insn_reloc (howto ))
1721
+ word = riscv_get_insn (howto -> bitsize , contents + rel -> r_offset );
1722
+ else
1723
+ word = bfd_get (howto -> bitsize , input_bfd , contents + rel -> r_offset );
1688
1724
word = (word & ~howto -> dst_mask ) | (value & howto -> dst_mask );
1689
- bfd_put (howto -> bitsize , input_bfd , word , contents + rel -> r_offset );
1725
+ if (riscv_is_insn_reloc (howto ))
1726
+ riscv_put_insn (howto -> bitsize , word , contents + rel -> r_offset );
1727
+ else
1728
+ bfd_put (howto -> bitsize , input_bfd , word , contents + rel -> r_offset );
1690
1729
1691
1730
return bfd_reloc_ok ;
1692
1731
}
@@ -1764,7 +1803,7 @@ riscv_zero_pcrel_hi_reloc (Elf_Internal_Rela *rel,
1764
1803
bfd_vma addr ,
1765
1804
bfd_byte * contents ,
1766
1805
const reloc_howto_type * howto ,
1767
- bfd * input_bfd )
1806
+ bfd * input_bfd ATTRIBUTE_UNUSED )
1768
1807
{
1769
1808
/* We may need to reference low addreses in PC-relative modes even when the
1770
1809
* PC is far away from these addresses. For example, undefweak references
@@ -1790,9 +1829,9 @@ riscv_zero_pcrel_hi_reloc (Elf_Internal_Rela *rel,
1790
1829
1791
1830
rel -> r_info = ELFNN_R_INFO (addr , R_RISCV_HI20 );
1792
1831
1793
- bfd_vma insn = bfd_get (howto -> bitsize , input_bfd , contents + rel -> r_offset );
1832
+ bfd_vma insn = riscv_get_insn (howto -> bitsize , contents + rel -> r_offset );
1794
1833
insn = (insn & ~MASK_AUIPC ) | MATCH_LUI ;
1795
- bfd_put (howto -> bitsize , input_bfd , insn , contents + rel -> r_offset );
1834
+ riscv_put_insn (howto -> bitsize , insn , contents + rel -> r_offset );
1796
1835
return TRUE;
1797
1836
}
1798
1837
@@ -2380,10 +2419,9 @@ riscv_elf_relocate_section (bfd *output_bfd,
2380
2419
&& (!bfd_link_pic (info ) || h -> plt .offset == MINUS_ONE ))
2381
2420
{
2382
2421
/* We can use x0 as the base register. */
2383
- bfd_vma insn = bfd_get_32 (input_bfd ,
2384
- contents + rel -> r_offset + 4 );
2422
+ bfd_vma insn = bfd_getl32 (contents + rel -> r_offset + 4 );
2385
2423
insn &= ~(OP_MASK_RS1 << OP_SH_RS1 );
2386
- bfd_put_32 ( input_bfd , insn , contents + rel -> r_offset + 4 );
2424
+ bfd_putl32 ( insn , contents + rel -> r_offset + 4 );
2387
2425
/* Set the relocation value so that we get 0 after the pc
2388
2426
relative adjustment. */
2389
2427
relocation = sec_addr (input_section ) + rel -> r_offset ;
@@ -2416,10 +2454,10 @@ riscv_elf_relocate_section (bfd *output_bfd,
2416
2454
if (VALID_ITYPE_IMM (relocation + rel -> r_addend ))
2417
2455
{
2418
2456
/* We can use tp as the base register. */
2419
- bfd_vma insn = bfd_get_32 ( input_bfd , contents + rel -> r_offset );
2457
+ bfd_vma insn = bfd_getl32 ( contents + rel -> r_offset );
2420
2458
insn &= ~(OP_MASK_RS1 << OP_SH_RS1 );
2421
2459
insn |= X_TP << OP_SH_RS1 ;
2422
- bfd_put_32 ( input_bfd , insn , contents + rel -> r_offset );
2460
+ bfd_putl32 ( insn , contents + rel -> r_offset );
2423
2461
}
2424
2462
else
2425
2463
r = bfd_reloc_overflow ;
@@ -2433,14 +2471,14 @@ riscv_elf_relocate_section (bfd *output_bfd,
2433
2471
if (x0_base || VALID_ITYPE_IMM (relocation + rel -> r_addend - gp ))
2434
2472
{
2435
2473
/* We can use x0 or gp as the base register. */
2436
- bfd_vma insn = bfd_get_32 ( input_bfd , contents + rel -> r_offset );
2474
+ bfd_vma insn = bfd_getl32 ( contents + rel -> r_offset );
2437
2475
insn &= ~(OP_MASK_RS1 << OP_SH_RS1 );
2438
2476
if (!x0_base )
2439
2477
{
2440
2478
rel -> r_addend -= gp ;
2441
2479
insn |= X_GP << OP_SH_RS1 ;
2442
2480
}
2443
- bfd_put_32 ( input_bfd , insn , contents + rel -> r_offset );
2481
+ bfd_putl32 ( insn , contents + rel -> r_offset );
2444
2482
}
2445
2483
else
2446
2484
r = bfd_reloc_overflow ;
@@ -2864,7 +2902,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
2864
2902
return FALSE;
2865
2903
2866
2904
for (i = 0 ; i < PLT_ENTRY_INSNS ; i ++ )
2867
- bfd_put_32 ( output_bfd , plt_entry [i ], loc + 4 * i );
2905
+ bfd_putl32 ( plt_entry [i ], loc + 4 * i );
2868
2906
2869
2907
/* Fill in the initial value of the .got.plt entry. */
2870
2908
loc = gotplt -> contents + (got_address - sec_addr (gotplt ));
@@ -3161,7 +3199,7 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd,
3161
3199
return ret ;
3162
3200
3163
3201
for (i = 0 ; i < PLT_HEADER_INSNS ; i ++ )
3164
- bfd_put_32 ( output_bfd , plt_header [i ], splt -> contents + 4 * i );
3202
+ bfd_putl32 ( plt_header [i ], splt -> contents + 4 * i );
3165
3203
3166
3204
elf_section_data (splt -> output_section )-> this_hdr .sh_entsize
3167
3205
= PLT_ENTRY_SIZE ;
@@ -4118,8 +4156,8 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
4118
4156
/* Shorten the function call. */
4119
4157
BFD_ASSERT (rel -> r_offset + 8 <= sec -> size );
4120
4158
4121
- auipc = bfd_get_32 ( abfd , contents + rel -> r_offset );
4122
- jalr = bfd_get_32 ( abfd , contents + rel -> r_offset + 4 );
4159
+ auipc = bfd_getl32 ( contents + rel -> r_offset );
4160
+ jalr = bfd_getl32 ( contents + rel -> r_offset + 4 );
4123
4161
rd = (jalr >> OP_SH_RD ) & OP_MASK_RD ;
4124
4162
rvc = rvc && VALID_RVC_J_IMM (foff );
4125
4163
@@ -4149,7 +4187,7 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
4149
4187
/* Replace the R_RISCV_CALL reloc. */
4150
4188
rel -> r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel -> r_info ), r_type );
4151
4189
/* Replace the AUIPC. */
4152
- bfd_put (8 * len , abfd , auipc , contents + rel -> r_offset );
4190
+ riscv_put_insn (8 * len , auipc , contents + rel -> r_offset );
4153
4191
4154
4192
/* Delete unnecessary JALR. */
4155
4193
* again = TRUE;
@@ -4223,9 +4261,9 @@ _bfd_riscv_relax_lui (bfd *abfd,
4223
4261
if (undefined_weak )
4224
4262
{
4225
4263
/* Change the RS1 to zero. */
4226
- bfd_vma insn = bfd_get_32 ( abfd , contents + rel -> r_offset );
4264
+ bfd_vma insn = bfd_getl32 ( contents + rel -> r_offset );
4227
4265
insn &= ~(OP_MASK_RS1 << OP_SH_RS1 );
4228
- bfd_put_32 ( abfd , insn , contents + rel -> r_offset );
4266
+ bfd_putl32 ( insn , contents + rel -> r_offset );
4229
4267
}
4230
4268
else
4231
4269
rel -> r_info = ELFNN_R_INFO (sym , R_RISCV_GPREL_I );
@@ -4235,9 +4273,9 @@ _bfd_riscv_relax_lui (bfd *abfd,
4235
4273
if (undefined_weak )
4236
4274
{
4237
4275
/* Change the RS1 to zero. */
4238
- bfd_vma insn = bfd_get_32 ( abfd , contents + rel -> r_offset );
4276
+ bfd_vma insn = bfd_getl32 ( contents + rel -> r_offset );
4239
4277
insn &= ~(OP_MASK_RS1 << OP_SH_RS1 );
4240
- bfd_put_32 ( abfd , insn , contents + rel -> r_offset );
4278
+ bfd_putl32 ( insn , contents + rel -> r_offset );
4241
4279
}
4242
4280
else
4243
4281
rel -> r_info = ELFNN_R_INFO (sym , R_RISCV_GPREL_S );
@@ -4268,13 +4306,13 @@ _bfd_riscv_relax_lui (bfd *abfd,
4268
4306
: ELF_MAXPAGESIZE )))
4269
4307
{
4270
4308
/* Replace LUI with C.LUI if legal (i.e., rd != x0 and rd != x2/sp). */
4271
- bfd_vma lui = bfd_get_32 ( abfd , contents + rel -> r_offset );
4309
+ bfd_vma lui = bfd_getl32 ( contents + rel -> r_offset );
4272
4310
unsigned rd = ((unsigned )lui >> OP_SH_RD ) & OP_MASK_RD ;
4273
4311
if (rd == 0 || rd == X_SP )
4274
4312
return TRUE;
4275
4313
4276
4314
lui = (lui & (OP_MASK_RD << OP_SH_RD )) | MATCH_C_LUI ;
4277
- bfd_put_32 ( abfd , lui , contents + rel -> r_offset );
4315
+ bfd_putl32 ( lui , contents + rel -> r_offset );
4278
4316
4279
4317
/* Replace the R_RISCV_HI20 reloc. */
4280
4318
rel -> r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel -> r_info ), R_RISCV_RVC_LUI );
@@ -4376,11 +4414,11 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
4376
4414
4377
4415
/* Write as many RISC-V NOPs as we need. */
4378
4416
for (pos = 0 ; pos < (nop_bytes & -4 ); pos += 4 )
4379
- bfd_put_32 ( abfd , RISCV_NOP , contents + rel -> r_offset + pos );
4417
+ bfd_putl32 ( RISCV_NOP , contents + rel -> r_offset + pos );
4380
4418
4381
4419
/* Write a final RVC NOP if need be. */
4382
4420
if (nop_bytes % 4 != 0 )
4383
- bfd_put_16 ( abfd , RVC_NOP , contents + rel -> r_offset + pos );
4421
+ bfd_putl16 ( RVC_NOP , contents + rel -> r_offset + pos );
4384
4422
4385
4423
/* Delete the excess bytes. */
4386
4424
return riscv_relax_delete_bytes (abfd , sec , rel -> r_offset + nop_bytes ,
@@ -4487,9 +4525,9 @@ _bfd_riscv_relax_pc (bfd *abfd ATTRIBUTE_UNUSED,
4487
4525
{
4488
4526
/* Change the RS1 to zero, and then modify the relocation
4489
4527
type to R_RISCV_LO12_I. */
4490
- bfd_vma insn = bfd_get_32 ( abfd , contents + rel -> r_offset );
4528
+ bfd_vma insn = bfd_getl32 ( contents + rel -> r_offset );
4491
4529
insn &= ~(OP_MASK_RS1 << OP_SH_RS1 );
4492
- bfd_put_32 ( abfd , insn , contents + rel -> r_offset );
4530
+ bfd_putl32 ( insn , contents + rel -> r_offset );
4493
4531
rel -> r_info = ELFNN_R_INFO (sym , R_RISCV_LO12_I );
4494
4532
rel -> r_addend = hi_reloc .hi_addend ;
4495
4533
}
@@ -4505,9 +4543,9 @@ _bfd_riscv_relax_pc (bfd *abfd ATTRIBUTE_UNUSED,
4505
4543
{
4506
4544
/* Change the RS1 to zero, and then modify the relocation
4507
4545
type to R_RISCV_LO12_S. */
4508
- bfd_vma insn = bfd_get_32 ( abfd , contents + rel -> r_offset );
4546
+ bfd_vma insn = bfd_getl32 ( contents + rel -> r_offset );
4509
4547
insn &= ~(OP_MASK_RS1 << OP_SH_RS1 );
4510
- bfd_put_32 ( abfd , insn , contents + rel -> r_offset );
4548
+ bfd_putl32 ( insn , contents + rel -> r_offset );
4511
4549
rel -> r_info = ELFNN_R_INFO (sym , R_RISCV_LO12_S );
4512
4550
rel -> r_addend = hi_reloc .hi_addend ;
4513
4551
}
@@ -4919,7 +4957,8 @@ static bfd_boolean
4919
4957
riscv_elf_object_p (bfd * abfd )
4920
4958
{
4921
4959
/* There are only two mach types in RISCV currently. */
4922
- if (strcmp (abfd -> xvec -> name , "elf32-littleriscv" ) == 0 )
4960
+ if (strcmp (abfd -> xvec -> name , "elf32-littleriscv" ) == 0
4961
+ || strcmp (abfd -> xvec -> name , "elf32-bigriscv" ) == 0 )
4923
4962
bfd_default_set_arch_mach (abfd , bfd_arch_riscv , bfd_mach_riscv32 );
4924
4963
else
4925
4964
bfd_default_set_arch_mach (abfd , bfd_arch_riscv , bfd_mach_riscv64 );
@@ -4938,6 +4977,8 @@ riscv_elf_obj_attrs_arg_type (int tag)
4938
4977
4939
4978
#define TARGET_LITTLE_SYM riscv_elfNN_vec
4940
4979
#define TARGET_LITTLE_NAME "elfNN-littleriscv"
4980
+ #define TARGET_BIG_SYM riscv_elfNN_be_vec
4981
+ #define TARGET_BIG_NAME "elfNN-bigriscv"
4941
4982
4942
4983
#define elf_backend_reloc_type_class riscv_reloc_type_class
4943
4984
0 commit comments