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 (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #include <string.h>
  27 #include "_libelf.h"
  28 #include "decl.h"
  29 #include "msg.h"
  30 
  31 
  32 /*
  33  * Find elf or it's class from a pointer to an Elf_Data struct.
  34  * Warning:  this Assumes that the Elf_Data is part of a libelf
  35  * Dnode structure, which is expected to be true for any Elf_Data
  36  * passed into libelf *except* for the xlatetof() and xlatetom() functions.
  37  */
  38 #define EDATA_CLASS(edata) \
  39         (((Dnode *)(edata))->db_scn->s_elf->ed_class)
  40 
  41 #define EDATA_ELF(edata) \
  42         (((Dnode *)(edata))->db_scn->s_elf)
  43 
  44 #define EDATA_SCN(edata) \
  45         (((Dnode *)(edata))->db_scn)
  46 
  47 #define EDATA_READLOCKS(edata) \
  48         READLOCKS(EDATA_ELF((edata)), EDATA_SCN((edata)))
  49 
  50 #define EDATA_READUNLOCKS(edata) \
  51         READUNLOCKS(EDATA_ELF((edata)), EDATA_SCN((edata)))
  52 
  53 
  54 size_t
  55 gelf_fsize(Elf * elf, Elf_Type type, size_t count, unsigned ver)
  56 {
  57         int class;
  58 
  59         if (elf == NULL)
  60                 return (0);
  61 
  62         class = gelf_getclass(elf);
  63         if (class == ELFCLASS32)
  64                 return (elf32_fsize(type, count, ver));
  65         else if (class == ELFCLASS64)
  66                 return (elf64_fsize(type, count, ver));
  67 
  68         _elf_seterr(EREQ_CLASS, 0);
  69         return (0);
  70 }
  71 
  72 
  73 int
  74 gelf_getclass(Elf *elf)
  75 {
  76         if (elf == NULL)
  77                 return (0);
  78 
  79         /*
  80          * Don't rely on the idents, a new ehdr doesn't have it!
  81          */
  82         return (elf->ed_class);
  83 }
  84 
  85 
  86 GElf_Ehdr *
  87 gelf_getehdr(Elf *elf, GElf_Ehdr *dst)
  88 {
  89         int class;
  90 
  91         if (elf == NULL)
  92                 return (NULL);
  93 
  94         class = gelf_getclass(elf);
  95         if (class == ELFCLASS32) {
  96                 Elf32_Ehdr * e          = elf32_getehdr(elf);
  97 
  98                 if (e == NULL)
  99                         return (NULL);
 100 
 101                 ELFRLOCK(elf);
 102                 (void) memcpy(dst->e_ident, e->e_ident, EI_NIDENT);
 103                 dst->e_type          = e->e_type;
 104                 dst->e_machine               = e->e_machine;
 105                 dst->e_version               = e->e_version;
 106                 dst->e_entry         = (Elf64_Addr)e->e_entry;
 107                 dst->e_phoff         = (Elf64_Off)e->e_phoff;
 108                 dst->e_shoff         = (Elf64_Off)e->e_shoff;
 109                 dst->e_flags         = e->e_flags;
 110                 dst->e_ehsize                = e->e_ehsize;
 111                 dst->e_phentsize     = e->e_phentsize;
 112                 dst->e_phnum         = e->e_phnum;
 113                 dst->e_shentsize     = e->e_shentsize;
 114                 dst->e_shnum         = e->e_shnum;
 115                 dst->e_shstrndx              = e->e_shstrndx;
 116                 ELFUNLOCK(elf);
 117 
 118                 return (dst);
 119         } else if (class == ELFCLASS64) {
 120                 Elf64_Ehdr * e          = elf64_getehdr(elf);
 121 
 122                 if (e == NULL)
 123                         return (NULL);
 124 
 125                 ELFRLOCK(elf);
 126                 *dst                    = *e;
 127                 ELFUNLOCK(elf);
 128 
 129                 return (dst);
 130         }
 131 
 132         _elf_seterr(EREQ_CLASS, 0);
 133         return (NULL);
 134 }
 135 
 136 
 137 int
 138 gelf_update_ehdr(Elf *elf, GElf_Ehdr *src)
 139 {
 140         int class;
 141 
 142         if (elf == NULL)
 143                 return (0);
 144 
 145         /*
 146          * In case elf isn't cooked.
 147          */
 148         class = gelf_getclass(elf);
 149         if (class == ELFCLASSNONE)
 150                 class = src->e_ident[EI_CLASS];
 151 
 152 
 153         if (class == ELFCLASS32) {
 154                 Elf32_Ehdr * d  = elf32_getehdr(elf);
 155 
 156                 if (d == NULL)
 157                         return (0);
 158 
 159                 ELFWLOCK(elf);
 160                 (void) memcpy(d->e_ident, src->e_ident, EI_NIDENT);
 161                 d->e_type    = src->e_type;
 162                 d->e_machine = src->e_machine;
 163                 d->e_version = src->e_version;
 164                 /* LINTED */
 165                 d->e_entry   = (Elf32_Addr)src->e_entry;
 166                 /* LINTED */
 167                 d->e_phoff   = (Elf32_Off)src->e_phoff;
 168                 /* LINTED */
 169                 d->e_shoff   = (Elf32_Off)src->e_shoff;
 170                 /* could memcpy the rest of these... */
 171                 d->e_flags   = src->e_flags;
 172                 d->e_ehsize  = src->e_ehsize;
 173                 d->e_phentsize       = src->e_phentsize;
 174                 d->e_phnum   = src->e_phnum;
 175                 d->e_shentsize       = src->e_shentsize;
 176                 d->e_shnum   = src->e_shnum;
 177                 d->e_shstrndx        = src->e_shstrndx;
 178                 ELFUNLOCK(elf);
 179 
 180                 return (1);
 181         } else if (class == ELFCLASS64) {
 182                 Elf64_Ehdr * d  = elf64_getehdr(elf);
 183 
 184                 if (d == NULL)
 185                         return (0);
 186 
 187                 ELFWLOCK(elf);
 188                 *d              = *(Elf64_Ehdr *)src;
 189                 ELFUNLOCK(elf);
 190 
 191                 return (1);
 192         }
 193 
 194         _elf_seterr(EREQ_CLASS, 0);
 195         return (0);
 196 }
 197 
 198 
 199 unsigned long
 200 gelf_newehdr(Elf *elf, int class)
 201 {
 202         if (elf == NULL)
 203                 return (0);
 204 
 205         if (class == ELFCLASS32)
 206                 return ((unsigned long)elf32_newehdr(elf));
 207         else if (class == ELFCLASS64)
 208                 return ((unsigned long)elf64_newehdr(elf));
 209 
 210         _elf_seterr(EREQ_CLASS, 0);
 211         return (0);
 212 }
 213 
 214 
 215 GElf_Phdr *
 216 gelf_getphdr(Elf *elf, int ndx, GElf_Phdr *dst)
 217 {
 218         int             class;
 219         size_t          phnum;
 220 
 221         if (elf == NULL)
 222                 return (NULL);
 223 
 224         if (elf_getphdrnum(elf, &phnum) == -1)
 225                 return (NULL);
 226 
 227         if (phnum <= ndx) {
 228                 _elf_seterr(EREQ_RAND, 0);
 229                 return (NULL);
 230         }
 231 
 232         class = gelf_getclass(elf);
 233         if ((class != ELFCLASS32) && (class != ELFCLASS64)) {
 234                 _elf_seterr(EREQ_CLASS, 0);
 235                 return (NULL);
 236         }
 237 
 238         if (class == ELFCLASS32) {
 239                 Elf32_Phdr *p   = &((Elf32_Phdr *)elf32_getphdr(elf))[ndx];
 240 
 241                 ELFRLOCK(elf);
 242                 dst->p_type  = p->p_type;
 243                 dst->p_flags = p->p_flags;
 244                 dst->p_offset        = (Elf64_Off)p->p_offset;
 245                 dst->p_vaddr = (Elf64_Addr)p->p_vaddr;
 246                 dst->p_paddr = (Elf64_Addr)p->p_paddr;
 247                 dst->p_filesz        = (Elf64_Xword)p->p_filesz;
 248                 dst->p_memsz = (Elf64_Xword)p->p_memsz;
 249                 dst->p_align = (Elf64_Xword)p->p_align;
 250                 ELFUNLOCK(elf);
 251         } else if (class == ELFCLASS64) {
 252                 Elf64_Phdr *phdrs = elf64_getphdr(elf);
 253                 ELFRLOCK(elf);
 254                 *dst = ((GElf_Phdr *)phdrs)[ndx];
 255                 ELFUNLOCK(elf);
 256         }
 257 
 258         return (dst);
 259 }
 260 
 261 
 262 int
 263 gelf_update_phdr(Elf *elf, int ndx, GElf_Phdr *src)
 264 {
 265         int             class;
 266         size_t          phnum;
 267 
 268         if (elf == NULL)
 269                 return (0);
 270 
 271         if (elf_getphdrnum(elf, &phnum) == -1)
 272                 return (NULL);
 273 
 274         if (phnum < ndx) {
 275                 _elf_seterr(EREQ_RAND, 0);
 276                 return (0);
 277         }
 278 
 279         class = gelf_getclass(elf);
 280         if (class == ELFCLASS32) {
 281                 Elf32_Phdr *dst = &((Elf32_Phdr *)elf32_getphdr(elf))[ndx];
 282                 ELFWLOCK(elf);
 283                 dst->p_type  = src->p_type;
 284                 dst->p_flags = src->p_flags;
 285                 /* LINTED */
 286                 dst->p_offset        = (Elf32_Off)src->p_offset;
 287                 /* LINTED */
 288                 dst->p_vaddr = (Elf32_Addr)src->p_vaddr;
 289                 /* LINTED */
 290                 dst->p_paddr = (Elf32_Addr)src->p_paddr;
 291                 /* LINTED */
 292                 dst->p_filesz        = (Elf32_Word)src->p_filesz;
 293                 /* LINTED */
 294                 dst->p_memsz = (Elf32_Word)src->p_memsz;
 295                 /* LINTED */
 296                 dst->p_align = (Elf32_Word)src->p_align;
 297                 ELFUNLOCK(elf);
 298         } else if (class == ELFCLASS64) {
 299                 Elf64_Phdr *dst = elf64_getphdr(elf);
 300                 ELFWLOCK(elf);
 301                 dst[ndx] = *(GElf_Phdr *)src;
 302                 ELFUNLOCK(elf);
 303         } else {
 304                 _elf_seterr(EREQ_CLASS, 0);
 305                 return (0);
 306         }
 307         return (1);
 308 }
 309 
 310 
 311 unsigned long
 312 gelf_newphdr(Elf *elf, size_t phnum)
 313 {
 314         int class;
 315 
 316         if (elf == NULL)
 317                 return (0);
 318 
 319         class = gelf_getclass(elf);
 320         if (class == ELFCLASS32)
 321                 return ((unsigned long)elf32_newphdr(elf, phnum));
 322         else if (class == ELFCLASS64)
 323                 return ((unsigned long)elf64_newphdr(elf, phnum));
 324 
 325         _elf_seterr(EREQ_CLASS, 0);
 326         return (0);
 327 }
 328 
 329 
 330 GElf_Shdr *
 331 gelf_getshdr(Elf_Scn *scn,  GElf_Shdr *dst)
 332 {
 333         if (scn == NULL)
 334                 return (NULL);
 335 
 336         if (scn->s_elf->ed_class == ELFCLASS32) {
 337                 Elf32_Shdr *s           = elf32_getshdr(scn);
 338 
 339                 if (s == NULL)
 340                         return (NULL);
 341 
 342                 READLOCKS(scn->s_elf, scn);
 343                 dst->sh_name         = s->sh_name;
 344                 dst->sh_type         = s->sh_type;
 345                 dst->sh_flags                = (Elf64_Xword)s->sh_flags;
 346                 dst->sh_addr         = (Elf64_Addr)s->sh_addr;
 347                 dst->sh_offset               = (Elf64_Off)s->sh_offset;
 348                 dst->sh_size         = (Elf64_Xword)s->sh_size;
 349                 dst->sh_link         = s->sh_link;
 350                 dst->sh_info         = s->sh_info;
 351                 dst->sh_addralign    = (Elf64_Xword)s->sh_addralign;
 352                 dst->sh_entsize              = (Elf64_Xword)s->sh_entsize;
 353                 READUNLOCKS(scn->s_elf, scn);
 354 
 355                 return (dst);
 356         } else if (scn->s_elf->ed_class == ELFCLASS64) {
 357                 Elf64_Shdr *s           = elf64_getshdr(scn);
 358 
 359                 if (s == NULL)
 360                         return (NULL);
 361 
 362                 READLOCKS(scn->s_elf, scn);
 363                 *dst                    = *(Elf64_Shdr *)s;
 364                 READUNLOCKS(scn->s_elf, scn);
 365 
 366                 return (dst);
 367         }
 368 
 369         _elf_seterr(EREQ_CLASS, 0);
 370         return (NULL);
 371 }
 372 
 373 
 374 int
 375 gelf_update_shdr(Elf_Scn *scn, GElf_Shdr *src)
 376 {
 377         if (scn == NULL)
 378                 return (0);
 379 
 380         if (scn->s_elf->ed_class == ELFCLASS32) {
 381                 Elf32_Shdr *dst = elf32_getshdr(scn);
 382 
 383                 if (dst == NULL)
 384                         return (0);
 385 
 386                 ELFWLOCK(scn->s_elf);
 387                 dst->sh_name         = src->sh_name;
 388                 dst->sh_type         = src->sh_type;
 389                 /* LINTED */
 390                 dst->sh_flags                = (Elf32_Word)src->sh_flags;
 391                 /* LINTED */
 392                 dst->sh_addr         = (Elf32_Addr)src->sh_addr;
 393                 /* LINTED */
 394                 dst->sh_offset               = (Elf32_Off) src->sh_offset;
 395                 /* LINTED */
 396                 dst->sh_size         = (Elf32_Word)src->sh_size;
 397                 dst->sh_link         = src->sh_link;
 398                 dst->sh_info         = src->sh_info;
 399                 /* LINTED */
 400                 dst->sh_addralign    = (Elf32_Word)src->sh_addralign;
 401                 /* LINTED */
 402                 dst->sh_entsize              = (Elf32_Word)src->sh_entsize;
 403 
 404                 ELFUNLOCK(scn->s_elf);
 405                 return (1);
 406         } else if (scn->s_elf->ed_class == ELFCLASS64) {
 407                 Elf64_Shdr * dst        = elf64_getshdr(scn);
 408 
 409                 if (dst == NULL)
 410                         return (0);
 411 
 412                 ELFWLOCK(scn->s_elf);
 413                 *dst                    = *(Elf64_Shdr *)src;
 414                 ELFUNLOCK(scn->s_elf);
 415                 return (1);
 416         }
 417 
 418         _elf_seterr(EREQ_CLASS, 0);
 419         return (0);
 420 }
 421 
 422 
 423 /*
 424  * gelf_xlatetof/gelf_xlatetom use 'elf' to find the class
 425  * because these are the odd case where the Elf_Data structs
 426  * might not have been allocated by libelf (and therefore
 427  * don't have Dnode's associated with them).
 428  */
 429 Elf_Data *
 430 gelf_xlatetof(Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode)
 431 {
 432         int class;
 433 
 434         if ((elf == NULL) || (dst == NULL) || (src == NULL))
 435                 return (NULL);
 436 
 437         class = gelf_getclass(elf);
 438         if (class == ELFCLASS32)
 439                 return (elf32_xlatetof(dst, src, encode));
 440         else if (class == ELFCLASS64)
 441                 return (elf64_xlatetof(dst, src, encode));
 442 
 443         _elf_seterr(EREQ_CLASS, 0);
 444         return (NULL);
 445 }
 446 
 447 
 448 Elf_Data *
 449 gelf_xlatetom(Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode)
 450 {
 451         int class;
 452 
 453         if ((elf == NULL) || (dst == NULL) || (src == NULL))
 454                 return (NULL);
 455 
 456         class = gelf_getclass(elf);
 457         if (class == ELFCLASS32)
 458                 return (elf32_xlatetom(dst, src, encode));
 459         else if (class == ELFCLASS64)
 460                 return (elf64_xlatetom(dst, src, encode));
 461 
 462         _elf_seterr(EREQ_CLASS, 0);
 463         return (NULL);
 464 }
 465 
 466 
 467 GElf_Sym *
 468 gelf_getsym(Elf_Data * data, int ndx, GElf_Sym * dst)
 469 {
 470         int     class;
 471         size_t  entsize;
 472 
 473         if (data == NULL)
 474                 return (NULL);
 475 
 476         class = EDATA_CLASS(data);
 477         if (class == ELFCLASS32)
 478                 entsize = sizeof (Elf32_Sym);
 479         else if (class == ELFCLASS64)
 480                 entsize = sizeof (GElf_Sym);
 481         else {
 482                 _elf_seterr(EREQ_CLASS, 0);
 483                 return (NULL);
 484         }
 485 
 486         EDATA_READLOCKS(data);
 487 
 488         if ((entsize * ndx) >= data->d_size) {
 489                 _elf_seterr(EREQ_RAND, 0);
 490                 dst = NULL;
 491         } else if (class == ELFCLASS32) {
 492                 Elf32_Sym       *s;
 493                 s               = &(((Elf32_Sym *)data->d_buf)[ndx]);
 494                 dst->st_name = s->st_name;
 495                 dst->st_value        = (Elf64_Addr)s->st_value;
 496                 dst->st_size = (Elf64_Xword)s->st_size;
 497                 dst->st_info = ELF64_ST_INFO(ELF32_ST_BIND(s->st_info),
 498                     ELF32_ST_TYPE(s->st_info));
 499                 dst->st_other        = s->st_other;
 500                 dst->st_shndx        = s->st_shndx;
 501         } else
 502                 *dst = ((GElf_Sym *)data->d_buf)[ndx];
 503 
 504         EDATA_READUNLOCKS(data);
 505         return (dst);
 506 }
 507 
 508 
 509 int
 510 gelf_update_sym(Elf_Data *dst, int ndx, GElf_Sym *src)
 511 {
 512         int     class, rc = 1;
 513         size_t  entsize;
 514 
 515         if (dst == NULL)
 516                 return (0);
 517 
 518         class = EDATA_CLASS(dst);
 519         if (class == ELFCLASS32)
 520                 entsize = sizeof (Elf32_Sym);
 521         else if (class == ELFCLASS64)
 522                 entsize = sizeof (GElf_Sym);
 523         else {
 524                 _elf_seterr(EREQ_CLASS, 0);
 525                 return (0);
 526         }
 527 
 528         ELFWLOCK(EDATA_ELF(dst));
 529 
 530         if ((entsize * ndx) >= dst->d_size) {
 531                 _elf_seterr(EREQ_RAND, 0);
 532                 rc = 0;
 533         } else if (class == ELFCLASS32) {
 534                 Elf32_Sym * d;
 535 
 536                 d               = &(((Elf32_Sym *)dst->d_buf)[ndx]);
 537                 d->st_name   = src->st_name;
 538                 /* LINTED */
 539                 d->st_value  = (Elf32_Addr)src->st_value;
 540                 /* LINTED */
 541                 d->st_size   = (Elf32_Word)src->st_size;
 542                 d->st_info   = ELF32_ST_INFO(ELF64_ST_BIND(src->st_info),
 543                     ELF64_ST_TYPE(src->st_info));
 544                 d->st_other  = src->st_other;
 545                 d->st_shndx  = src->st_shndx;
 546         } else
 547                 ((Elf64_Sym *)dst->d_buf)[ndx] = *((Elf64_Sym *)src);
 548 
 549         ELFUNLOCK(EDATA_ELF(dst));
 550         return (rc);
 551 }
 552 
 553 
 554 GElf_Syminfo *
 555 gelf_getsyminfo(Elf_Data *data, int ndx, GElf_Syminfo *dst)
 556 {
 557         int     class;
 558         size_t  entsize;
 559 
 560         if (data == NULL)
 561                 return (NULL);
 562 
 563         class = EDATA_CLASS(data);
 564         if (class == ELFCLASS32)
 565                 entsize = sizeof (Elf32_Syminfo);
 566         else if (class == ELFCLASS64)
 567                 entsize = sizeof (GElf_Syminfo);
 568         else {
 569                 _elf_seterr(EREQ_CLASS, 0);
 570                 return (NULL);
 571         }
 572         EDATA_READLOCKS(data);
 573 
 574         if ((entsize * ndx) >= data->d_size) {
 575                 _elf_seterr(EREQ_RAND, 0);
 576                 dst = NULL;
 577         } else if (class == ELFCLASS32) {
 578                 Elf32_Syminfo * si;
 579 
 580                 si              = &(((Elf32_Syminfo *)data->d_buf)[ndx]);
 581                 dst->si_boundto = si->si_boundto;
 582                 dst->si_flags        = si->si_flags;
 583         } else
 584                 *dst            = ((GElf_Syminfo *)data->d_buf)[ndx];
 585 
 586         EDATA_READUNLOCKS(data);
 587         return (dst);
 588 }
 589 
 590 int
 591 gelf_update_syminfo(Elf_Data *dst, int ndx, GElf_Syminfo *src)
 592 {
 593         int     class, rc = 1;
 594         size_t  entsize;
 595 
 596         if (dst == NULL)
 597                 return (0);
 598 
 599         class = EDATA_CLASS(dst);
 600         if (class == ELFCLASS32)
 601                 entsize = sizeof (Elf32_Syminfo);
 602         else if (class == ELFCLASS64)
 603                 entsize = sizeof (GElf_Syminfo);
 604         else {
 605                 _elf_seterr(EREQ_CLASS, 0);
 606                 return (0);
 607         }
 608         ELFWLOCK(EDATA_ELF(dst));
 609 
 610         if ((entsize * ndx) >= dst->d_size) {
 611                 _elf_seterr(EREQ_RAND, 0);
 612                 rc = 0;
 613         } else if (class == ELFCLASS32) {
 614                 Elf32_Syminfo * d       = &(((Elf32_Syminfo *)dst->d_buf)[ndx]);
 615                 d->si_boundto                = src->si_boundto;
 616                 d->si_flags          = src->si_flags;
 617         } else
 618                 ((Elf64_Syminfo *)dst->d_buf)[ndx] = *((Elf64_Syminfo *)src);
 619 
 620         ELFUNLOCK(EDATA_ELF(dst));
 621         return (rc);
 622 }
 623 
 624 GElf_Dyn *
 625 gelf_getdyn(Elf_Data *data, int ndx, GElf_Dyn *dst)
 626 {
 627         int     class;
 628         size_t  entsize;
 629 
 630         if (data == NULL)
 631                 return (NULL);
 632 
 633         class = EDATA_CLASS(data);
 634         if (class == ELFCLASS32)
 635                 entsize = sizeof (Elf32_Dyn);
 636         else if (class == ELFCLASS64)
 637                 entsize = sizeof (GElf_Dyn);
 638         else {
 639                 _elf_seterr(EREQ_CLASS, 0);
 640                 return (NULL);
 641         }
 642         EDATA_READLOCKS(data);
 643 
 644         if ((entsize * ndx) >= data->d_size) {
 645                 _elf_seterr(EREQ_RAND, 0);
 646                 dst = NULL;
 647         } else if (class == ELFCLASS32) {
 648                 Elf32_Dyn * d = &((Elf32_Dyn *)data->d_buf)[ndx];
 649 
 650                 dst->d_tag   = (Elf32_Sword)d->d_tag;
 651                 dst->d_un.d_val      = (Elf32_Word) d->d_un.d_val;
 652         } else
 653                 *dst = ((Elf64_Dyn *)data->d_buf)[ndx];
 654 
 655         EDATA_READUNLOCKS(data);
 656         return (dst);
 657 }
 658 
 659 
 660 int
 661 gelf_update_dyn(Elf_Data *dst, int ndx, GElf_Dyn *src)
 662 {
 663         int     class, rc = 1;
 664         size_t  entsize;
 665 
 666         if (dst == NULL)
 667                 return (0);
 668 
 669         class = EDATA_CLASS(dst);
 670         if (class == ELFCLASS32)
 671                 entsize = sizeof (Elf32_Dyn);
 672         else if (class == ELFCLASS64)
 673                 entsize = sizeof (GElf_Dyn);
 674         else {
 675                 _elf_seterr(EREQ_CLASS, 0);
 676                 return (0);
 677         }
 678         ELFWLOCK(EDATA_ELF(dst));
 679 
 680         if ((entsize * ndx) >= dst->d_size) {
 681                 _elf_seterr(EREQ_RAND, 0);
 682                 rc = 0;
 683         } else if (class == ELFCLASS32) {
 684                 Elf32_Dyn * d = &((Elf32_Dyn *)dst->d_buf)[ndx];
 685 
 686                 /* LINTED */
 687                 d->d_tag     = (Elf32_Word)src->d_tag;
 688                 /* LINTED */
 689                 d->d_un.d_val        = (Elf32_Word)src->d_un.d_val;
 690         } else
 691                 ((Elf64_Dyn *)dst->d_buf)[ndx] = *(Elf64_Dyn*)src;
 692 
 693         ELFUNLOCK(EDATA_ELF(dst));
 694         return (rc);
 695 }
 696 
 697 
 698 
 699 GElf_Sym *
 700 gelf_getsymshndx(Elf_Data *symdata, Elf_Data *shndxdata,
 701     int ndx, GElf_Sym *symptr, Elf32_Word *xshndx)
 702 {
 703         if (gelf_getsym(symdata, ndx, symptr) == 0)
 704                 return (NULL);
 705         if (shndxdata && xshndx) {
 706                 EDATA_READLOCKS(shndxdata);
 707                 if ((ndx * sizeof (Elf32_Word)) >= shndxdata->d_size) {
 708                         _elf_seterr(EREQ_RAND, 0);
 709                         EDATA_READUNLOCKS(shndxdata);
 710                         return (NULL);
 711                 }
 712                 *xshndx = (((Elf32_Word *)shndxdata->d_buf)[ndx]);
 713                 EDATA_READUNLOCKS(shndxdata);
 714         } else {
 715                 *xshndx = 0;
 716         }
 717         return (symptr);
 718 }
 719 
 720 int
 721 gelf_update_symshndx(Elf_Data *symdata, Elf_Data *shndxdata,
 722     int ndx, GElf_Sym *symptr, Elf32_Word xshndx)
 723 {
 724         if (gelf_update_sym(symdata, ndx, symptr) == 0)
 725                 return (0);
 726         if (shndxdata) {
 727                 ELFWLOCK(EDATA_ELF(shndxdata));
 728                 if ((ndx * sizeof (Elf32_Word)) >= shndxdata->d_size) {
 729                         _elf_seterr(EREQ_RAND, 0);
 730                         ELFUNLOCK(EDATA_ELF(shndxdata));
 731                         return (0);
 732                 }
 733                 ((Elf32_Word *)shndxdata->d_buf)[ndx] = xshndx;
 734                 ELFUNLOCK(EDATA_ELF(shndxdata));
 735         }
 736         return (1);
 737 }
 738 
 739 
 740 GElf_Move *
 741 gelf_getmove(Elf_Data *src, int ndx, GElf_Move *dst)
 742 {
 743         int     class;
 744         size_t  entsize;
 745 
 746         if (src == NULL)
 747                 return (NULL);
 748 
 749         class = EDATA_CLASS(src);
 750         if (class == ELFCLASS32)
 751                 entsize = sizeof (Elf32_Move);
 752         else if (class == ELFCLASS64)
 753                 entsize = sizeof (GElf_Move);
 754         else {
 755                 _elf_seterr(EREQ_CLASS, 0);
 756                 return (NULL);
 757         }
 758         EDATA_READLOCKS(src);
 759 
 760         if ((entsize * ndx) >= src->d_size) {
 761                 _elf_seterr(EREQ_RAND, 0);
 762                 dst = NULL;
 763         } else if (class == ELFCLASS32) {
 764                 Elf32_Move * m = &((Elf32_Move *)src->d_buf)[ndx];
 765 
 766                 dst->m_poffset = (Elf64_Word)m->m_poffset;
 767                 dst->m_repeat = (Elf64_Xword)m->m_repeat;
 768                 dst->m_stride = (Elf64_Half)m->m_stride;
 769                 dst->m_value = (Elf64_Xword)m->m_value;
 770                 dst->m_info = ELF64_M_INFO(ELF32_M_SYM(m->m_info),
 771                     ELF32_M_SIZE(m->m_info));
 772         } else {
 773                 *dst = ((Elf64_Move *)src->d_buf)[ndx];
 774         }
 775 
 776         EDATA_READUNLOCKS(src);
 777         return (dst);
 778 }
 779 
 780 int
 781 gelf_update_move(Elf_Data *dest, int ndx, GElf_Move *src)
 782 {
 783         int     class, rc = 1;
 784         size_t  entsize;
 785 
 786         if (dest == NULL)
 787                 return (0);
 788 
 789         class = EDATA_CLASS(dest);
 790         if (class == ELFCLASS32)
 791                 entsize = sizeof (Elf32_Move);
 792         else if (class == ELFCLASS64)
 793                 entsize = sizeof (GElf_Move);
 794         else {
 795                 _elf_seterr(EREQ_CLASS, 0);
 796                 return (0);
 797         }
 798         ELFWLOCK(EDATA_ELF(dest));
 799 
 800         if ((entsize * ndx) >= dest->d_size) {
 801                 _elf_seterr(EREQ_RAND, 0);
 802                 rc = 0;
 803         } else if (class == ELFCLASS32) {
 804                 Elf32_Move * m = &((Elf32_Move *)dest->d_buf)[ndx];
 805 
 806                 m->m_poffset = (Elf32_Word)src->m_poffset;
 807                 m->m_repeat = (Elf32_Half)src->m_repeat;
 808                 m->m_stride = (Elf32_Half)src->m_stride;
 809                 m->m_value = (Elf32_Lword)src->m_value;
 810                 m->m_info = (Elf32_Word)ELF32_M_INFO(ELF64_M_SYM(src->m_info),
 811                     ELF64_M_SIZE(src->m_info));
 812         } else {
 813                 ((Elf64_Move *)dest->d_buf)[ndx] = *(Elf64_Move *)src;
 814         }
 815 
 816         ELFUNLOCK(EDATA_ELF(dest));
 817         return (rc);
 818 }
 819 
 820 
 821 GElf_Rela *
 822 gelf_getrela(Elf_Data *src, int ndx, GElf_Rela *dst)
 823 {
 824         int     class;
 825         size_t  entsize;
 826 
 827         if (src == NULL)
 828                 return (NULL);
 829 
 830         class = EDATA_CLASS(src);
 831         if (class == ELFCLASS32)
 832                 entsize = sizeof (Elf32_Rela);
 833         else if (class == ELFCLASS64)
 834                 entsize = sizeof (GElf_Rela);
 835         else {
 836                 _elf_seterr(EREQ_CLASS, 0);
 837                 return (NULL);
 838         }
 839         EDATA_READLOCKS(src);
 840 
 841         if ((entsize * ndx) >= src->d_size) {
 842                 _elf_seterr(EREQ_RAND, 0);
 843                 dst = NULL;
 844         } else if (class == ELFCLASS32) {
 845                 Elf32_Rela * r = &((Elf32_Rela *)src->d_buf)[ndx];
 846 
 847                 dst->r_offset        = (GElf_Addr)r->r_offset;
 848                 dst->r_addend        = (GElf_Addr)r->r_addend;
 849 
 850                 /*
 851                  * Elf32 will never have the extra data field that
 852                  * Elf64's r_info field can have, so ignore it.
 853                  */
 854                 /* LINTED */
 855                 dst->r_info  = ELF64_R_INFO(
 856                     ELF32_R_SYM(r->r_info),
 857                     ELF32_R_TYPE(r->r_info));
 858         } else
 859                 *dst = ((Elf64_Rela *)src->d_buf)[ndx];
 860 
 861         EDATA_READUNLOCKS(src);
 862         return (dst);
 863 }
 864 
 865 
 866 int
 867 gelf_update_rela(Elf_Data *dst, int ndx, GElf_Rela *src)
 868 {
 869         int     class, rc = 1;
 870         size_t  entsize;
 871 
 872         if (dst == NULL)
 873                 return (0);
 874 
 875         class = EDATA_CLASS(dst);
 876         if (class == ELFCLASS32)
 877                 entsize = sizeof (Elf32_Rela);
 878         else if (class == ELFCLASS64)
 879                 entsize = sizeof (GElf_Rela);
 880         else {
 881                 _elf_seterr(EREQ_CLASS, 0);
 882                 return (0);
 883         }
 884         ELFWLOCK(EDATA_ELF(dst));
 885 
 886         if ((entsize * ndx) >= dst->d_size) {
 887                 _elf_seterr(EREQ_RAND, 0);
 888                 rc = 0;
 889         } else if (class == ELFCLASS32) {
 890                 Elf32_Rela * r = &((Elf32_Rela *)dst->d_buf)[ndx];
 891 
 892                 /* LINTED */
 893                 r->r_offset  = (Elf32_Addr) src->r_offset;
 894                 /* LINTED */
 895                 r->r_addend  = (Elf32_Sword)src->r_addend;
 896 
 897                 /*
 898                  * Elf32 will never have the extra data field that
 899                  * Elf64's r_info field can have, so ignore it.
 900                  */
 901                 /* LINTED */
 902                 r->r_info    = ELF32_R_INFO(ELF64_R_SYM(src->r_info),
 903                     ELF64_R_TYPE(src->r_info));
 904         } else {
 905                 ((Elf64_Rela *)dst->d_buf)[ndx] = *(Elf64_Rela *)src;
 906         }
 907 
 908         ELFUNLOCK(EDATA_ELF(dst));
 909 
 910         return (rc);
 911 }
 912 
 913 
 914 GElf_Rel *
 915 gelf_getrel(Elf_Data *src, int ndx, GElf_Rel *dst)
 916 {
 917         int     class;
 918         size_t  entsize;
 919 
 920         if (src == NULL)
 921                 return (NULL);
 922 
 923         class = EDATA_CLASS(src);
 924         if (class == ELFCLASS32)
 925                 entsize = sizeof (Elf32_Rel);
 926         else if (class == ELFCLASS64)
 927                 entsize = sizeof (GElf_Rel);
 928         else {
 929                 _elf_seterr(EREQ_CLASS, 0);
 930                 return (NULL);
 931         }
 932         EDATA_READLOCKS(src);
 933 
 934         if ((entsize * ndx) >= src->d_size) {
 935                 _elf_seterr(EREQ_RAND, 0);
 936                 dst = NULL;
 937         } else if (class == ELFCLASS32) {
 938                 Elf32_Rel * r = &((Elf32_Rel *)src->d_buf)[ndx];
 939 
 940                 dst->r_offset        = (GElf_Addr)r->r_offset;
 941 
 942                 /*
 943                  * Elf32 will never have the extra data field that
 944                  * Elf64's r_info field can have, so ignore it.
 945                  */
 946                 /* LINTED */
 947                 dst->r_info  = ELF64_R_INFO(ELF32_R_SYM(r->r_info),
 948                     ELF32_R_TYPE(r->r_info));
 949         } else
 950                 *dst = ((Elf64_Rel *)src->d_buf)[ndx];
 951 
 952         EDATA_READUNLOCKS(src);
 953         return (dst);
 954 }
 955 
 956 
 957 int
 958 gelf_update_rel(Elf_Data *dst, int ndx, GElf_Rel *src)
 959 {
 960         int     class, rc = 1;
 961         size_t  entsize;
 962 
 963         if (dst == NULL)
 964                 return (0);
 965 
 966         class = EDATA_CLASS(dst);
 967         if (class == ELFCLASS32)
 968                 entsize = sizeof (Elf32_Rel);
 969         else if (class == ELFCLASS64)
 970                 entsize = sizeof (GElf_Rel);
 971         else {
 972                 _elf_seterr(EREQ_CLASS, 0);
 973                 return (0);
 974         }
 975         ELFWLOCK(EDATA_ELF(dst));
 976 
 977         if ((entsize * ndx) >= dst->d_size) {
 978                 _elf_seterr(EREQ_RAND, 0);
 979                 rc = 0;
 980         } else if (class == ELFCLASS32) {
 981                 Elf32_Rel * r = &((Elf32_Rel *)dst->d_buf)[ndx];
 982 
 983                 /* LINTED */
 984                 r->r_offset  = (Elf32_Addr) src->r_offset;
 985 
 986                 /*
 987                  * Elf32 will never have the extra data field that
 988                  * Elf64's r_info field can have, so ignore it.
 989                  */
 990                 /* LINTED */
 991                 r->r_info    = ELF32_R_INFO(ELF64_R_SYM(src->r_info),
 992                     ELF64_R_TYPE(src->r_info));
 993 
 994         } else {
 995                 ((Elf64_Rel *)dst->d_buf)[ndx] = *(Elf64_Rel *)src;
 996         }
 997 
 998         ELFUNLOCK(EDATA_ELF(dst));
 999         return (rc);
1000 }
1001 
1002 long
1003 gelf_checksum(Elf *elf)
1004 {
1005         int class = gelf_getclass(elf);
1006 
1007         if (class == ELFCLASS32)
1008                 return (elf32_checksum(elf));
1009         else if (class == ELFCLASS64)
1010                 return (elf64_checksum(elf));
1011 
1012         _elf_seterr(EREQ_CLASS, 0);
1013         return (0);
1014 }
1015 
1016 GElf_Cap *
1017 gelf_getcap(Elf_Data *data, int ndx, GElf_Cap *dst)
1018 {
1019         int     class;
1020         size_t  entsize;
1021 
1022         if (data == NULL)
1023                 return (NULL);
1024 
1025         class = EDATA_CLASS(data);
1026         if (class == ELFCLASS32)
1027                 entsize = sizeof (Elf32_Cap);
1028         else if (class == ELFCLASS64)
1029                 entsize = sizeof (GElf_Cap);
1030         else {
1031                 _elf_seterr(EREQ_CLASS, 0);
1032                 return (NULL);
1033         }
1034 
1035         EDATA_READLOCKS(data);
1036 
1037         if ((entsize * ndx) >= data->d_size) {
1038                 _elf_seterr(EREQ_RAND, 0);
1039                 dst = NULL;
1040         } else if (class == ELFCLASS32) {
1041                 Elf32_Cap       *c = &(((Elf32_Cap *)data->d_buf)[ndx]);
1042 
1043                 dst->c_tag = (Elf64_Xword)c->c_tag;
1044                 dst->c_un.c_val = (Elf64_Xword)c->c_un.c_val;
1045         } else
1046                 *dst = ((GElf_Cap *)data->d_buf)[ndx];
1047 
1048         EDATA_READUNLOCKS(data);
1049         return (dst);
1050 }
1051 
1052 int
1053 gelf_update_cap(Elf_Data *dst, int ndx, GElf_Cap *src)
1054 {
1055         int     class, rc = 1;
1056         size_t  entsize;
1057 
1058         if (dst == NULL)
1059                 return (0);
1060 
1061         class = EDATA_CLASS(dst);
1062         if (class == ELFCLASS32)
1063                 entsize = sizeof (Elf32_Cap);
1064         else if (class == ELFCLASS64)
1065                 entsize = sizeof (GElf_Cap);
1066         else {
1067                 _elf_seterr(EREQ_CLASS, 0);
1068                 return (0);
1069         }
1070 
1071         ELFWLOCK(EDATA_ELF(dst));
1072 
1073         if ((entsize * ndx) >= dst->d_size) {
1074                 _elf_seterr(EREQ_RAND, 0);
1075                 rc = 0;
1076         } else if (class == ELFCLASS32) {
1077                 Elf32_Cap       *c = &(((Elf32_Cap *)dst->d_buf)[ndx]);
1078 
1079                 c->c_tag = (Elf32_Word)src->c_tag;
1080                 c->c_un.c_val = (Elf32_Word)src->c_un.c_val;
1081         } else
1082                 ((Elf64_Cap *)dst->d_buf)[ndx] = *((Elf64_Cap *)src);
1083 
1084         ELFUNLOCK(EDATA_ELF(dst));
1085         return (rc);
1086 }
1087 
1088 /*
1089  * If the specified object has a dynamic section, and that section
1090  * contains a DT_FLAGS_1 entry, then return the value of that entry.
1091  * Otherwise, return 0.
1092  */
1093 GElf_Xword
1094 _gelf_getdynval(Elf *elf, GElf_Sxword tag)
1095 {
1096         Elf_Scn *scn = NULL;
1097         Elf_Data *data;
1098         GElf_Shdr shdr;
1099         GElf_Dyn dyn;
1100         int i, n;
1101 
1102         while (scn = elf_nextscn(elf, scn)) {
1103                 if (gelf_getshdr(scn, &shdr) == NULL)
1104                         break;
1105                 if (shdr.sh_type != SHT_DYNAMIC)
1106                         continue;
1107                 if (data = elf_getdata(scn, NULL)) {
1108                         n = shdr.sh_size / shdr.sh_entsize;
1109                         for (i = 0; i < n; i++) {
1110                                 (void) gelf_getdyn(data, i, &dyn);
1111                                 if (dyn.d_tag == tag) {
1112                                         return (dyn.d_un.d_val);
1113                                 }
1114                         }
1115                 }
1116                 break;
1117         }
1118         return (0);
1119 }
1120 
1121 GElf_Xword
1122 _gelf_getdyndtflags_1(Elf *elf)
1123 {
1124         return (_gelf_getdynval(elf, DT_FLAGS_1));
1125 }