1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <libelf.h> 29 #include <dlfcn.h> 30 #include "machdep.h" 31 #include "reloc.h" 32 #include "msg.h" 33 #include "_librtld.h" 34 35 static const char *unknown = 0; /* Stash MSG_INTL(MSG_STR_UNKNOWN) */ 36 37 /* 38 * Process all relocation records. A new `Reloc' structure is allocated to 39 * cache the processing decisions deduced, and these will be applied during 40 * update_reloc(). 41 * A count of the number of null relocations (i.e., relocations that will be 42 * fixed and whoes records will be nulled out), data and function relocations 43 * is maintained. This allows the relocation records themselves to be 44 * rearranged (localized) later if necessary. Note that the number of function 45 * relocations, although coounted, shouldn't differ from the original file, 46 * the index of a .plt must be maintained to the index of its relocation record 47 * within the associated relocation section. 48 * 49 * The intention behind this file is to maintain as much relocation logic as 50 * possible in a generic form. 51 */ 52 int 53 count_reloc(Cache *cache, Cache *_cache, Rt_map *lmp, int flags, Addr addr, 54 Xword *null, Xword *data, Xword *func) 55 { 56 Rel *rel; 57 Reloc *reloc; 58 Shdr *shdr; 59 Xword ent, cnt, _cnt; 60 Sym *syms; 61 const char *strs; 62 Cache *__cache; 63 Xword pltndx = 0; 64 65 /* 66 * Determine the number of relocation entries we'll be dealing with. 67 */ 68 shdr = _cache->c_shdr; 69 rel = (Rel *)_cache->c_data->d_buf; 70 ent = shdr->sh_entsize; 71 cnt = shdr->sh_size / ent; 72 73 /* 74 * Allocate a relocation structure for this relocation section. 75 */ 76 if ((reloc = calloc(cnt, sizeof (Reloc))) == 0) 77 return (1); 78 _cache->c_info = (void *)reloc; 79 80 /* 81 * Determine the relocations associated symbol and string table. 82 */ 83 __cache = &cache[shdr->sh_link]; 84 syms = (Sym *)__cache->c_data->d_buf; 85 shdr = __cache->c_shdr; 86 __cache = &cache[shdr->sh_link]; 87 strs = (const char *)__cache->c_data->d_buf; 88 89 /* 90 * Loop through the relocation table. 91 */ 92 for (_cnt = 0; _cnt < cnt; _cnt++, reloc++, 93 rel = (Rel *)((uintptr_t)rel + ent)) { 94 const char *name; 95 /* LINTED */ 96 uchar_t type = (uchar_t)ELF_R_TYPE(rel->r_info); 97 uchar_t bind; 98 ulong_t offset = rel->r_offset + addr; 99 Rt_map *_lmp; 100 int _bound, _weak; 101 ulong_t rsymndx = ELF_R_SYM(rel->r_info); 102 Slookup sl; 103 uint_t binfo; 104 Sym *_sym, *sym = (syms + rsymndx); 105 106 if (type == M_R_JMP_SLOT) 107 reloc->r_pltndx = ++pltndx; 108 109 /* 110 * Analyze the case where no relocations are to be applied. 111 */ 112 if ((flags & RTLD_REL_ALL) == 0) { 113 /* 114 * Don't apply any relocations to the new image but 115 * insure their offsets are incremented to reflect any 116 * new fixed address. 117 */ 118 reloc->r_flags = FLG_R_INC; 119 120 /* 121 * Undo any relocations that might have already been 122 * applied to the memory image. 123 */ 124 if (flags & RTLD_MEMORY) { 125 reloc->r_flags |= FLG_R_UNDO; 126 127 /* 128 * If a copy relocation is involved we'll need 129 * to know the size of the copy. 130 */ 131 if (type == M_R_COPY) 132 reloc->r_size = sym->st_size; 133 else 134 reloc->r_size = 0; 135 } 136 137 /* 138 * Save the objects new address. 139 */ 140 reloc->r_value = addr; 141 142 if (type == M_R_JMP_SLOT) 143 (*func)++; 144 else 145 (*data)++; 146 continue; 147 } 148 149 /* 150 * Determine the symbol binding of the relocation. Don't assume 151 * that relative relocations are simply M_R_RELATIVE. Although 152 * a pic generated shared object can normally be viewed as 153 * having relative and non-relative relocations, a non-pic 154 * shared object will contain a number of relocations against 155 * local symbols (normally sections). If a relocation is 156 * against a local symbol it qualifies as a relative relocation. 157 */ 158 if ((type == M_R_RELATIVE) || (type == M_R_NONE) || 159 (ELF_ST_BIND(sym->st_info) == STB_LOCAL)) 160 bind = STB_LOCAL; 161 else 162 bind = STB_GLOBAL; 163 164 /* 165 * Analyze the case where only relative relocations are to be 166 * applied. 167 */ 168 if ((flags & RTLD_REL_ALL) == RTLD_REL_RELATIVE) { 169 if (flags & RTLD_MEMORY) { 170 if (bind == STB_LOCAL) { 171 /* 172 * Save the relative relocations from 173 * the memory image. The data itself 174 * might already have been relocated, 175 * thus clear the relocation record so 176 * that it will not be performed again. 177 */ 178 reloc->r_flags = FLG_R_CLR; 179 (*null)++; 180 } else { 181 /* 182 * Any non-relative relocation must be 183 * undone, and the relocation records 184 * offset updated to any new fixed 185 * address. 186 */ 187 reloc->r_flags = 188 (FLG_R_UNDO | FLG_R_INC); 189 reloc->r_value = addr; 190 if (type == M_R_JMP_SLOT) 191 (*func)++; 192 else 193 (*data)++; 194 } 195 } else { 196 if (bind == STB_LOCAL) { 197 /* 198 * Apply relative relocation to the 199 * file image. Clear the relocation 200 * record so that it will not be 201 * performed again. 202 */ 203 reloc->r_flags = 204 (FLG_R_APPLY | FLG_R_CLR); 205 reloc->r_value = addr; 206 if (IS_PC_RELATIVE(type)) 207 reloc->r_value -= offset; 208 209 if (unknown == 0) 210 unknown = MSG_INTL(MSG_STR_UNKNOWN); 211 reloc->r_name = unknown; 212 (*null)++; 213 } else { 214 /* 215 * Any non-relative relocation should be 216 * left alone, but its offset should be 217 * updated to any new fixed address. 218 */ 219 reloc->r_flags = FLG_R_INC; 220 reloc->r_value = addr; 221 if (type == M_R_JMP_SLOT) 222 (*func)++; 223 else 224 (*data)++; 225 } 226 } 227 continue; 228 } 229 230 /* 231 * Analyze the case where more than just relative relocations 232 * are to be applied. 233 */ 234 if (bind == STB_LOCAL) { 235 if (flags & RTLD_MEMORY) { 236 /* 237 * Save the relative relocations from the memory 238 * image. The data itself has already been 239 * relocated, thus clear the relocation record 240 * so that it will not be performed again. 241 */ 242 reloc->r_flags = FLG_R_CLR; 243 } else { 244 /* 245 * Apply relative relocation to the file image. 246 * Clear the relocation record so that it will 247 * not be performed again. 248 */ 249 reloc->r_flags = (FLG_R_APPLY | FLG_R_CLR); 250 reloc->r_value = addr; 251 if (IS_PC_RELATIVE(type)) 252 reloc->r_value -= offset; 253 254 if (unknown == 0) 255 unknown = MSG_INTL(MSG_STR_UNKNOWN); 256 reloc->r_name = unknown; 257 } 258 (*null)++; 259 continue; 260 } 261 262 /* 263 * At this point we're dealing with a non-relative relocation 264 * that requires the symbol definition. 265 */ 266 name = strs + sym->st_name; 267 268 /* 269 * Find the symbol. As the object being investigated is already 270 * a part of this process, the symbol lookup will likely 271 * succeed. However, because of lazy binding, there is still 272 * the possibility of a dangling .plt relocation. dldump() 273 * users might be encouraged to set LD_FLAGS=loadavail (crle(1) 274 * does this for them). 275 */ 276 sl.sl_name = name; 277 sl.sl_cmap = lmp; 278 sl.sl_imap = LIST(lmp)->lm_head; 279 sl.sl_hash = 0; 280 sl.sl_rsymndx = rsymndx; 281 282 if (type == M_R_COPY) 283 sl.sl_flags = LKUP_COPY; 284 else 285 sl.sl_flags = LKUP_DEFT; 286 287 _bound = _weak = 0; 288 _sym = sym; 289 if ((sym = lookup_sym(&sl, &_lmp, &binfo)) != 0) { 290 /* 291 * Determine from the various relocation requirements 292 * whether this binding is appropriate. If we're called 293 * from crle(1), RTLD_CONFSET is set, then only inspect 294 * objects selected from the configuration file 295 * (FL1_RT_CONFSET was set during load()). 296 */ 297 if (!(flags & RTLD_CONFSET) || 298 (FLAGS1(_lmp) & FL1_RT_CONFSET)) { 299 if (((flags & RTLD_REL_ALL) == RTLD_REL_ALL) || 300 ((flags & RTLD_REL_EXEC) && 301 (FLAGS(_lmp) & FLG_RT_ISMAIN)) || 302 ((flags & RTLD_REL_DEPENDS) && 303 (!(FLAGS(_lmp) & FLG_RT_ISMAIN))) || 304 ((flags & RTLD_REL_PRELOAD) && 305 (FLAGS(_lmp) & FLG_RT_PRELOAD)) || 306 ((flags & RTLD_REL_SELF) && (lmp == _lmp))) 307 _bound = 1; 308 } 309 } else { 310 /* 311 * If this is a weak reference and we've been asked to 312 * bind unresolved weak references consider ourself 313 * bound. This category is typically set by clre(1) for 314 * an application cache. 315 */ 316 if ((ELF_ST_BIND(_sym->st_info) == STB_WEAK) && 317 (_sym->st_shndx == SHN_UNDEF) && 318 (flags & RTLD_REL_WEAK)) 319 _bound = _weak = 1; 320 } 321 322 if (flags & RTLD_MEMORY) { 323 if (_bound) { 324 /* 325 * We know that all data relocations will have 326 * been performed at process startup thus clear 327 * the relocation record so that it will not be 328 * performed again. However, we don't know what 329 * function relocations have been performed 330 * because of lazy binding - regardless, we can 331 * leave all the function relocation records in 332 * place, because if the function has already 333 * been bound the record won't be referenced 334 * anyway. In the case of using LD_BIND_NOW, 335 * a function may be bound twice - so what. 336 */ 337 if (type == M_R_JMP_SLOT) { 338 reloc->r_flags = FLG_R_INC; 339 (*func)++; 340 } else { 341 if (type != M_R_COPY) 342 reloc->r_flags = FLG_R_CLR; 343 (*null)++; 344 } 345 } else { 346 /* 347 * Clear any unrequired relocation. 348 */ 349 reloc->r_flags = FLG_R_UNDO | FLG_R_INC; 350 reloc->r_value = addr; 351 if (type == M_R_JMP_SLOT) 352 (*func)++; 353 else 354 (*data)++; 355 } 356 } else { 357 if (_bound) { 358 /* 359 * Apply the global relocation to the file 360 * image. Clear the relocation record so that 361 * it will not be performed again. 362 */ 363 if (_weak) { 364 reloc->r_value = 0; 365 reloc->r_size = 0; 366 } else { 367 reloc->r_value = sym->st_value; 368 if (IS_PC_RELATIVE(type)) 369 reloc->r_value -= offset; 370 if ((!(FLAGS(_lmp) & FLG_RT_FIXED)) && 371 (sym->st_shndx != SHN_ABS)) 372 reloc->r_value += ADDR(_lmp); 373 reloc->r_size = sym->st_size; 374 } 375 376 reloc->r_flags = FLG_R_APPLY | FLG_R_CLR; 377 reloc->r_name = name; 378 if (type == M_R_JMP_SLOT) 379 (*func)++; 380 else 381 (*null)++; 382 } else { 383 /* 384 * Do not apply any unrequired relocations. 385 */ 386 reloc->r_flags = FLG_R_INC; 387 reloc->r_value = addr; 388 if (type == M_R_JMP_SLOT) 389 (*func)++; 390 else 391 (*data)++; 392 } 393 } 394 } 395 return (0); 396 } 397 398 399 /* 400 * Perform any relocation updates to the new image using the information from 401 * the `Reloc' structure constructed during count_reloc(). 402 */ 403 void 404 update_reloc(Cache *ocache, Cache *icache, Cache *_icache, const char *name, 405 Rt_map *lmp, Rel **null, Rel **data, Rel **func) 406 { 407 Shdr *shdr; 408 Rel *rel; 409 Reloc *reloc; 410 Xword ent, cnt, _cnt; 411 Cache *orcache, *ircache = 0; 412 Half ndx; 413 414 /* 415 * Set up to read the output relocation table. 416 */ 417 shdr = _icache->c_shdr; 418 rel = (Rel *)_icache->c_data->d_buf; 419 reloc = (Reloc *)_icache->c_info; 420 ent = shdr->sh_entsize; 421 cnt = shdr->sh_size / ent; 422 423 /* 424 * Loop through the relocation table. 425 */ 426 for (_cnt = 0; _cnt < cnt; _cnt++, reloc++, 427 rel = (Rel *)((uintptr_t)rel + ent)) { 428 uchar_t *iaddr, *oaddr; 429 /* LINTED */ 430 uchar_t type = (uchar_t)ELF_R_TYPE(rel->r_info); 431 Addr off, bgn, end; 432 433 /* 434 * Ignore null relocations (these may have been created from a 435 * previous dldump() of this image). 436 */ 437 if (type == M_R_NONE) { 438 (*null)++; 439 continue; 440 } 441 442 /* 443 * Determine the section being relocated if we haven't already 444 * done so (we may have had to skip over some null relocation to 445 * get to the first valid offset). The System V ABI states that 446 * a relocation sections sh_info field indicates the section 447 * that must be relocated. However, on Intel it seems that the 448 * .rel.plt sh_info records the section index of the .plt, when 449 * in fact it's the .got that gets relocated. In addition we 450 * now create combined relocation sections with -zcomreloc. To 451 * generically be able to cope with these anomalies, search for 452 * the appropriate section to be relocated by comparing the 453 * offset of the first relocation record against each sections 454 * offset and size. 455 */ 456 #if !defined(__lint) 457 if ((ircache == (Cache *)0) || (rel->r_offset < bgn) || 458 (rel->r_offset > end)) { 459 #else 460 /* 461 * lint sees `bgn' and `end' as potentially referenced 462 * before being set. 463 */ 464 if (ircache == (Cache *)0) { 465 #endif 466 _icache = icache; 467 _icache++; 468 469 for (ndx = 1; _icache->c_flags != FLG_C_END; ndx++, 470 _icache++) { 471 472 shdr = _icache->c_shdr; 473 bgn = shdr->sh_addr; 474 end = bgn + shdr->sh_size; 475 476 if ((rel->r_offset >= bgn) && 477 (rel->r_offset <= end)) 478 break; 479 } 480 ircache = &icache[ndx]; 481 orcache = &ocache[ndx]; 482 } 483 484 /* 485 * Determine the relocation location of both the input and 486 * output data. Take into account that an input section may be 487 * NOBITS (ppc .plt for example). 488 */ 489 off = rel->r_offset - ircache->c_shdr->sh_addr; 490 if (ircache->c_data->d_buf) 491 iaddr = (uchar_t *)ircache->c_data->d_buf + off; 492 else 493 iaddr = 0; 494 oaddr = (uchar_t *)orcache->c_data->d_buf + off; 495 496 /* 497 * Apply the relocation to the new output image. Any base 498 * address, or symbol value, will have been saved in the reloc 499 * structure during count_reloc(). 500 */ 501 if (reloc->r_flags & FLG_R_APPLY) 502 apply_reloc(rel, reloc, name, oaddr, lmp); 503 504 /* 505 * Undo any relocation that might already been applied to the 506 * memory image by the runtime linker. Using the original 507 * file, determine the relocation offset original value and 508 * restore the new image to that value. 509 */ 510 if ((reloc->r_flags & FLG_R_UNDO) && 511 (FLAGS(lmp) & FLG_RT_RELOCED)) 512 undo_reloc(rel, oaddr, iaddr, reloc); 513 514 /* 515 * If a relocation has been applied then the relocation record 516 * should be cleared so that the relocation isn't applied again 517 * when the new image is used. 518 */ 519 if (reloc->r_flags & FLG_R_CLR) { 520 if (type == M_R_JMP_SLOT) { 521 clear_reloc(*func); 522 *func = (Rel *)((uintptr_t)*func + ent); 523 } else { 524 clear_reloc(*null); 525 *null = (Rel *)((uintptr_t)*null + ent); 526 } 527 } 528 529 /* 530 * If a relocation isn't applied, update the relocation record 531 * to take into account the new address of the image. 532 */ 533 if (reloc->r_flags & FLG_R_INC) { 534 if (type == M_R_JMP_SLOT) { 535 inc_reloc(*func, rel, reloc, oaddr, iaddr); 536 *func = (Rel *)((uintptr_t)*func + ent); 537 } else { 538 inc_reloc(*data, rel, reloc, oaddr, iaddr); 539 *data = (Rel *)((uintptr_t)*data + ent); 540 } 541 } 542 } 543 } 544