@@ -533,16 +533,15 @@ static int read_symbols(struct elf *elf)
533533 return -1 ;
534534}
535535
536- static struct section * elf_create_reloc_section (struct elf * elf ,
537- struct section * sec ,
538- int reltype );
536+ static struct section * elf_create_rela_section (struct elf * elf ,
537+ struct section * sec );
539538
540539int elf_add_reloc (struct elf * elf , struct section * sec , unsigned long offset ,
541540 unsigned int type , struct symbol * sym , s64 addend )
542541{
543542 struct reloc * reloc ;
544543
545- if (!sec -> rsec && !elf_create_reloc_section (elf , sec , SHT_RELA ))
544+ if (!sec -> rsec && !elf_create_rela_section (elf , sec ))
546545 return -1 ;
547546
548547 reloc = malloc (sizeof (* reloc ));
@@ -865,29 +864,25 @@ int elf_add_reloc_to_insn(struct elf *elf, struct section *sec,
865864 return elf_add_reloc (elf , sec , offset , type , sym , addend );
866865}
867866
868- static int read_rel_reloc (struct section * rsec , int i , struct reloc * reloc , unsigned int * symndx )
867+ static int read_reloc (struct section * rsec , int i , struct reloc * reloc )
869868{
870- if (!gelf_getrel (rsec -> data , i , & reloc -> rel )) {
871- WARN_ELF ("gelf_getrel" );
872- return -1 ;
873- }
874- reloc -> type = GELF_R_TYPE (reloc -> rel .r_info );
875- reloc -> addend = 0 ;
876- reloc -> offset = reloc -> rel .r_offset ;
877- * symndx = GELF_R_SYM (reloc -> rel .r_info );
878- return 0 ;
879- }
869+ bool rela = rsec -> sh .sh_type == SHT_RELA ;
870+ void * retp ;
880871
881- static int read_rela_reloc (struct section * rsec , int i , struct reloc * reloc , unsigned int * symndx )
882- {
883- if (!gelf_getrela (rsec -> data , i , & reloc -> rela )) {
872+ if (rela )
873+ retp = gelf_getrela (rsec -> data , i , & reloc -> rela );
874+ else
875+ retp = gelf_getrel (rsec -> data , i , & reloc -> rel );
876+
877+ if (!retp ) {
884878 WARN_ELF ("gelf_getrela" );
885879 return -1 ;
886880 }
887- reloc -> type = GELF_R_TYPE (reloc -> rela .r_info );
888- reloc -> addend = reloc -> rela .r_addend ;
889- reloc -> offset = reloc -> rela .r_offset ;
890- * symndx = GELF_R_SYM (reloc -> rela .r_info );
881+
882+ reloc -> offset = reloc -> rel .r_offset ;
883+ reloc -> type = GELF_R_TYPE (reloc -> rel .r_info );
884+ reloc -> addend = rela ? reloc -> rela .r_addend : 0 ;
885+
891886 return 0 ;
892887}
893888
@@ -926,20 +921,13 @@ static int read_relocs(struct elf *elf)
926921 }
927922 for (i = 0 ; i < rsec -> sh .sh_size / rsec -> sh .sh_entsize ; i ++ ) {
928923 reloc = & rsec -> reloc_data [i ];
929- switch (rsec -> sh .sh_type ) {
930- case SHT_REL :
931- if (read_rel_reloc (rsec , i , reloc , & symndx ))
932- return -1 ;
933- break ;
934- case SHT_RELA :
935- if (read_rela_reloc (rsec , i , reloc , & symndx ))
936- return -1 ;
937- break ;
938- default : return -1 ;
939- }
924+
925+ if (read_reloc (rsec , i , reloc ))
926+ return -1 ;
940927
941928 reloc -> sec = rsec ;
942929 reloc -> idx = i ;
930+ symndx = GELF_R_SYM (reloc -> rel .r_info );
943931 reloc -> sym = sym = find_symbol_by_index (elf , symndx );
944932 if (!reloc -> sym ) {
945933 WARN ("can't find reloc entry symbol %d for %s" ,
@@ -1141,86 +1129,42 @@ struct section *elf_create_section(struct elf *elf, const char *name,
11411129 return sec ;
11421130}
11431131
1144- static struct section * elf_create_rel_reloc_section (struct elf * elf ,
1145- struct section * sec )
1132+ static struct section * elf_create_rela_section (struct elf * elf ,
1133+ struct section * sec )
11461134{
1147- char * relocname ;
11481135 struct section * rsec ;
1136+ char * rsec_name ;
11491137
1150- relocname = malloc (strlen (sec -> name ) + strlen (".rel " ) + 1 );
1151- if (!relocname ) {
1138+ rsec_name = malloc (strlen (sec -> name ) + strlen (".rela " ) + 1 );
1139+ if (!rsec_name ) {
11521140 perror ("malloc" );
11531141 return NULL ;
11541142 }
1155- strcpy (relocname , ".rel " );
1156- strcat (relocname , sec -> name );
1143+ strcpy (rsec_name , ".rela " );
1144+ strcat (rsec_name , sec -> name );
11571145
1158- rsec = elf_create_section (elf , relocname , sizeof ( GElf_Rel ), 0 );
1159- free (relocname );
1146+ rsec = elf_create_section (elf , rsec_name , elf_rela_size ( elf ), 0 );
1147+ free (rsec_name );
11601148 if (!rsec )
11611149 return NULL ;
11621150
11631151 sec -> rsec = rsec ;
11641152 rsec -> base = sec ;
11651153
1166- rsec -> sh .sh_type = SHT_REL ;
1167- rsec -> sh .sh_addralign = 8 ;
1168- rsec -> sh .sh_link = find_section_by_name (elf , ".symtab" )-> idx ;
1169- rsec -> sh .sh_info = sec -> idx ;
1170- rsec -> sh .sh_flags = SHF_INFO_LINK ;
1171-
1172- return rsec ;
1173- }
1174-
1175- static struct section * elf_create_rela_reloc_section (struct elf * elf , struct section * base )
1176- {
1177- char * relocname ;
1178- struct section * rsec ;
1179- int addrsize = elf_class_addrsize (elf );
1180-
1181- relocname = malloc (strlen (base -> name ) + strlen (".rela" ) + 1 );
1182- if (!relocname ) {
1183- perror ("malloc" );
1184- return NULL ;
1185- }
1186- strcpy (relocname , ".rela" );
1187- strcat (relocname , base -> name );
1188-
1189- if (addrsize == sizeof (u32 ))
1190- rsec = elf_create_section (elf , relocname , sizeof (Elf32_Rela ), 0 );
1191- else
1192- rsec = elf_create_section (elf , relocname , sizeof (GElf_Rela ), 0 );
1193- free (relocname );
1194- if (!rsec )
1195- return NULL ;
1196-
1197- base -> rsec = rsec ;
1198- rsec -> base = base ;
1199-
12001154 rsec -> sh .sh_type = SHT_RELA ;
1201- rsec -> sh .sh_addralign = addrsize ;
1155+ rsec -> sh .sh_addralign = elf_addr_size ( elf ) ;
12021156 rsec -> sh .sh_link = find_section_by_name (elf , ".symtab" )-> idx ;
1203- rsec -> sh .sh_info = base -> idx ;
1157+ rsec -> sh .sh_info = sec -> idx ;
12041158 rsec -> sh .sh_flags = SHF_INFO_LINK ;
12051159
12061160 return rsec ;
12071161}
12081162
1209- static struct section * elf_create_reloc_section (struct elf * elf ,
1210- struct section * base ,
1211- int reltype )
1212- {
1213- switch (reltype ) {
1214- case SHT_REL : return elf_create_rel_reloc_section (elf , base );
1215- case SHT_RELA : return elf_create_rela_reloc_section (elf , base );
1216- default : return NULL ;
1217- }
1218- }
1219-
1220- static int elf_rebuild_rel_reloc_section (struct section * rsec )
1163+ static int elf_rebuild_reloc_section (struct elf * elf , struct section * rsec )
12211164{
1165+ bool rela = rsec -> sh .sh_type == SHT_RELA ;
12221166 struct reloc * reloc ;
1223- int idx = 0 ;
1167+ int idx = 0 , ret ;
12241168 void * buf ;
12251169
12261170 /* Allocate a buffer for relocations */
@@ -1232,46 +1176,20 @@ static int elf_rebuild_rel_reloc_section(struct section *rsec)
12321176
12331177 rsec -> data -> d_buf = buf ;
12341178 rsec -> data -> d_size = rsec -> sh .sh_size ;
1235- rsec -> data -> d_type = ELF_T_REL ;
1179+ rsec -> data -> d_type = rela ? ELF_T_RELA : ELF_T_REL ;
12361180
12371181 idx = 0 ;
12381182 list_for_each_entry (reloc , & rsec -> reloc_list , list ) {
12391183 reloc -> rel .r_offset = reloc -> offset ;
12401184 reloc -> rel .r_info = GELF_R_INFO (reloc -> sym -> idx , reloc -> type );
1241- if (!gelf_update_rel (rsec -> data , idx , & reloc -> rel )) {
1242- WARN_ELF ("gelf_update_rel" );
1243- return -1 ;
1185+ if (rela ) {
1186+ reloc -> rela .r_addend = reloc -> addend ;
1187+ ret = gelf_update_rela (rsec -> data , idx , & reloc -> rela );
1188+ } else {
1189+ ret = gelf_update_rel (rsec -> data , idx , & reloc -> rel );
12441190 }
1245- idx ++ ;
1246- }
1247-
1248- return 0 ;
1249- }
1250-
1251- static int elf_rebuild_rela_reloc_section (struct section * rsec )
1252- {
1253- struct reloc * reloc ;
1254- int idx = 0 ;
1255- void * buf ;
1256-
1257- /* Allocate a buffer for relocations with addends */
1258- buf = malloc (rsec -> sh .sh_size );
1259- if (!buf ) {
1260- perror ("malloc" );
1261- return -1 ;
1262- }
1263-
1264- rsec -> data -> d_buf = buf ;
1265- rsec -> data -> d_size = rsec -> sh .sh_size ;
1266- rsec -> data -> d_type = ELF_T_RELA ;
1267-
1268- idx = 0 ;
1269- list_for_each_entry (reloc , & rsec -> reloc_list , list ) {
1270- reloc -> rela .r_offset = reloc -> offset ;
1271- reloc -> rela .r_addend = reloc -> addend ;
1272- reloc -> rela .r_info = GELF_R_INFO (reloc -> sym -> idx , reloc -> type );
1273- if (!gelf_update_rela (rsec -> data , idx , & reloc -> rela )) {
1274- WARN_ELF ("gelf_update_rela" );
1191+ if (!ret ) {
1192+ WARN_ELF ("gelf_update_rel" );
12751193 return -1 ;
12761194 }
12771195 idx ++ ;
@@ -1280,15 +1198,6 @@ static int elf_rebuild_rela_reloc_section(struct section *rsec)
12801198 return 0 ;
12811199}
12821200
1283- static int elf_rebuild_reloc_section (struct elf * elf , struct section * rsec )
1284- {
1285- switch (rsec -> sh .sh_type ) {
1286- case SHT_REL : return elf_rebuild_rel_reloc_section (rsec );
1287- case SHT_RELA : return elf_rebuild_rela_reloc_section (rsec );
1288- default : return -1 ;
1289- }
1290- }
1291-
12921201int elf_write_insn (struct elf * elf , struct section * sec ,
12931202 unsigned long offset , unsigned int len ,
12941203 const char * insn )
@@ -1311,24 +1220,21 @@ int elf_write_insn(struct elf *elf, struct section *sec,
13111220int elf_write_reloc (struct elf * elf , struct reloc * reloc )
13121221{
13131222 struct section * rsec = reloc -> sec ;
1223+ int ret ;
13141224
1315- if (rsec -> sh .sh_type == SHT_REL ) {
1316- reloc -> rel .r_info = GELF_R_INFO (reloc -> sym -> idx , reloc -> type );
1317- reloc -> rel .r_offset = reloc -> offset ;
1225+ reloc -> rel .r_offset = reloc -> offset ;
1226+ reloc -> rel .r_info = GELF_R_INFO (reloc -> sym -> idx , reloc -> type );
13181227
1319- if (!gelf_update_rel (rsec -> data , reloc -> idx , & reloc -> rel )) {
1320- WARN_ELF ("gelf_update_rel" );
1321- return -1 ;
1322- }
1323- } else {
1324- reloc -> rela .r_info = GELF_R_INFO (reloc -> sym -> idx , reloc -> type );
1228+ if (rsec -> sh .sh_type == SHT_RELA ) {
13251229 reloc -> rela .r_addend = reloc -> addend ;
1326- reloc -> rela .r_offset = reloc -> offset ;
1230+ ret = gelf_update_rela (rsec -> data , reloc -> idx , & reloc -> rela );
1231+ } else {
1232+ ret = gelf_update_rel (rsec -> data , reloc -> idx , & reloc -> rel );
1233+ }
13271234
1328- if (!gelf_update_rela (rsec -> data , reloc -> idx , & reloc -> rela )) {
1329- WARN_ELF ("gelf_update_rela" );
1330- return -1 ;
1331- }
1235+ if (!ret ) {
1236+ WARN_ELF ("gelf_update_rela" );
1237+ return -1 ;
13321238 }
13331239
13341240 elf -> changed = true;
0 commit comments