Print this page
4005 libctf can't deal with extended sections


 176  */
 177 void
 178 ctf_sect_munmap(const ctf_sect_t *sp)
 179 {
 180         uintptr_t addr = (uintptr_t)sp->cts_data;
 181         uintptr_t pageoff = addr & ~_PAGEMASK;
 182 
 183         (void) munmap((void *)(addr - pageoff), sp->cts_size + pageoff);
 184 }
 185 
 186 /*
 187  * Open the specified file descriptor and return a pointer to a CTF container.
 188  * The file can be either an ELF file or raw CTF file.  The caller is
 189  * responsible for closing the file descriptor when it is no longer needed.
 190  */
 191 ctf_file_t *
 192 ctf_fdopen(int fd, int *errp)
 193 {
 194         ctf_sect_t ctfsect, symsect, strsect;
 195         ctf_file_t *fp = NULL;

 196 
 197         struct stat64 st;
 198         ssize_t nbytes;
 199 
 200         union {
 201                 ctf_preamble_t ctf;
 202                 Elf32_Ehdr e32;
 203                 GElf_Ehdr e64;
 204         } hdr;
 205 
 206         bzero(&ctfsect, sizeof (ctf_sect_t));
 207         bzero(&symsect, sizeof (ctf_sect_t));
 208         bzero(&strsect, sizeof (ctf_sect_t));
 209         bzero(&hdr.ctf, sizeof (hdr));
 210 
 211         if (fstat64(fd, &st) == -1)
 212                 return (ctf_set_open_errno(errp, errno));
 213 
 214         if ((nbytes = pread64(fd, &hdr.ctf, sizeof (hdr), 0)) <= 0)
 215                 return (ctf_set_open_errno(errp, nbytes < 0? errno : ECTF_FMT));


 238 
 239                 if ((fp = ctf_bufopen(&ctfsect, NULL, NULL, errp)) == NULL)
 240                         ctf_sect_munmap(&ctfsect);
 241 
 242                 return (fp);
 243         }
 244 
 245         /*
 246          * If we have read enough bytes to form an ELF header and the magic
 247          * string matches, attempt to interpret the file as an ELF file.  We
 248          * do our own largefile ELF processing, and convert everything to
 249          * GElf structures so that clients can operate on any data model.
 250          */
 251         if (nbytes >= sizeof (Elf32_Ehdr) &&
 252             bcmp(&hdr.e32.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0) {
 253 #ifdef  _BIG_ENDIAN
 254                 uchar_t order = ELFDATA2MSB;
 255 #else
 256                 uchar_t order = ELFDATA2LSB;
 257 #endif
 258                 GElf_Half i, n;
 259                 GElf_Shdr *sp;
 260 
 261                 void *strs_map;
 262                 size_t strs_mapsz;
 263                 const char *strs;
 264 
 265                 if (hdr.e32.e_ident[EI_DATA] != order)
 266                         return (ctf_set_open_errno(errp, ECTF_ENDIAN));
 267                 if (hdr.e32.e_version != EV_CURRENT)
 268                         return (ctf_set_open_errno(errp, ECTF_ELFVERS));
 269 
 270                 if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS64) {
 271                         if (nbytes < sizeof (GElf_Ehdr))
 272                                 return (ctf_set_open_errno(errp, ECTF_FMT));
 273                 } else {
 274                         Elf32_Ehdr e32 = hdr.e32;
 275                         ehdr_to_gelf(&e32, &hdr.e64);
 276                 }
 277 
 278                 if (hdr.e64.e_shstrndx >= hdr.e64.e_shnum)




























 279                         return (ctf_set_open_errno(errp, ECTF_CORRUPT));
 280 
 281                 n = hdr.e64.e_shnum;
 282                 nbytes = sizeof (GElf_Shdr) * n;
 283 
 284                 if ((sp = malloc(nbytes)) == NULL)
 285                         return (ctf_set_open_errno(errp, errno));
 286 
 287                 /*
 288                  * Read in and convert to GElf the array of Shdr structures
 289                  * from e_shoff so we can locate sections of interest.
 290                  */
 291                 if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) {
 292                         Elf32_Shdr *sp32;
 293 
 294                         nbytes = sizeof (Elf32_Shdr) * n;
 295 
 296                         if ((sp32 = malloc(nbytes)) == NULL || pread64(fd,
 297                             sp32, nbytes, hdr.e64.e_shoff) != nbytes) {
 298                                 free(sp);
 299                                 return (ctf_set_open_errno(errp, errno));
 300                         }
 301 
 302                         for (i = 0; i < n; i++)
 303                                 shdr_to_gelf(&sp32[i], &sp[i]);
 304 
 305                         free(sp32);
 306 
 307                 } else if (pread64(fd, sp, nbytes, hdr.e64.e_shoff) != nbytes) {
 308                         free(sp);
 309                         return (ctf_set_open_errno(errp, errno));
 310                 }
 311 
 312                 /*
 313                  * Now mmap the section header strings section so that we can
 314                  * perform string comparison on the section names.
 315                  */
 316                 strs_mapsz = sp[hdr.e64.e_shstrndx].sh_size +
 317                     (sp[hdr.e64.e_shstrndx].sh_offset & ~_PAGEMASK);
 318 
 319                 strs_map = mmap64(NULL, strs_mapsz, PROT_READ, MAP_PRIVATE,
 320                     fd, sp[hdr.e64.e_shstrndx].sh_offset & _PAGEMASK);
 321 
 322                 strs = (const char *)strs_map +
 323                     (sp[hdr.e64.e_shstrndx].sh_offset & ~_PAGEMASK);
 324 
 325                 if (strs_map == MAP_FAILED) {
 326                         free(sp);
 327                         return (ctf_set_open_errno(errp, ECTF_MMAP));
 328                 }
 329 
 330                 /*
 331                  * Iterate over the section header array looking for the CTF
 332                  * section and symbol table.  The strtab is linked to symtab.
 333                  */
 334                 for (i = 0; i < n; i++) {
 335                         const GElf_Shdr *shp = &sp[i];
 336                         const GElf_Shdr *lhp = &sp[shp->sh_link];
 337 
 338                         if (shp->sh_link >= hdr.e64.e_shnum)
 339                                 continue; /* corrupt sh_link field */
 340 
 341                         if (shp->sh_name >= sp[hdr.e64.e_shstrndx].sh_size ||
 342                             lhp->sh_name >= sp[hdr.e64.e_shstrndx].sh_size)
 343                                 continue; /* corrupt sh_name field */
 344 
 345                         if (shp->sh_type == SHT_PROGBITS &&
 346                             strcmp(strs + shp->sh_name, _CTF_SECTION) == 0) {
 347                                 ctfsect.cts_name = strs + shp->sh_name;
 348                                 ctfsect.cts_type = shp->sh_type;
 349                                 ctfsect.cts_flags = shp->sh_flags;
 350                                 ctfsect.cts_size = shp->sh_size;
 351                                 ctfsect.cts_entsize = shp->sh_entsize;
 352                                 ctfsect.cts_offset = (off64_t)shp->sh_offset;
 353 
 354                         } else if (shp->sh_type == SHT_SYMTAB) {
 355                                 symsect.cts_name = strs + shp->sh_name;
 356                                 symsect.cts_type = shp->sh_type;
 357                                 symsect.cts_flags = shp->sh_flags;
 358                                 symsect.cts_size = shp->sh_size;
 359                                 symsect.cts_entsize = shp->sh_entsize;
 360                                 symsect.cts_offset = (off64_t)shp->sh_offset;
 361 
 362                                 strsect.cts_name = strs + lhp->sh_name;




 176  */
 177 void
 178 ctf_sect_munmap(const ctf_sect_t *sp)
 179 {
 180         uintptr_t addr = (uintptr_t)sp->cts_data;
 181         uintptr_t pageoff = addr & ~_PAGEMASK;
 182 
 183         (void) munmap((void *)(addr - pageoff), sp->cts_size + pageoff);
 184 }
 185 
 186 /*
 187  * Open the specified file descriptor and return a pointer to a CTF container.
 188  * The file can be either an ELF file or raw CTF file.  The caller is
 189  * responsible for closing the file descriptor when it is no longer needed.
 190  */
 191 ctf_file_t *
 192 ctf_fdopen(int fd, int *errp)
 193 {
 194         ctf_sect_t ctfsect, symsect, strsect;
 195         ctf_file_t *fp = NULL;
 196         size_t shstrndx, shnum;
 197 
 198         struct stat64 st;
 199         ssize_t nbytes;
 200 
 201         union {
 202                 ctf_preamble_t ctf;
 203                 Elf32_Ehdr e32;
 204                 GElf_Ehdr e64;
 205         } hdr;
 206 
 207         bzero(&ctfsect, sizeof (ctf_sect_t));
 208         bzero(&symsect, sizeof (ctf_sect_t));
 209         bzero(&strsect, sizeof (ctf_sect_t));
 210         bzero(&hdr.ctf, sizeof (hdr));
 211 
 212         if (fstat64(fd, &st) == -1)
 213                 return (ctf_set_open_errno(errp, errno));
 214 
 215         if ((nbytes = pread64(fd, &hdr.ctf, sizeof (hdr), 0)) <= 0)
 216                 return (ctf_set_open_errno(errp, nbytes < 0? errno : ECTF_FMT));


 239 
 240                 if ((fp = ctf_bufopen(&ctfsect, NULL, NULL, errp)) == NULL)
 241                         ctf_sect_munmap(&ctfsect);
 242 
 243                 return (fp);
 244         }
 245 
 246         /*
 247          * If we have read enough bytes to form an ELF header and the magic
 248          * string matches, attempt to interpret the file as an ELF file.  We
 249          * do our own largefile ELF processing, and convert everything to
 250          * GElf structures so that clients can operate on any data model.
 251          */
 252         if (nbytes >= sizeof (Elf32_Ehdr) &&
 253             bcmp(&hdr.e32.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0) {
 254 #ifdef  _BIG_ENDIAN
 255                 uchar_t order = ELFDATA2MSB;
 256 #else
 257                 uchar_t order = ELFDATA2LSB;
 258 #endif

 259                 GElf_Shdr *sp;
 260 
 261                 void *strs_map;
 262                 size_t strs_mapsz, i;
 263                 const char *strs;
 264 
 265                 if (hdr.e32.e_ident[EI_DATA] != order)
 266                         return (ctf_set_open_errno(errp, ECTF_ENDIAN));
 267                 if (hdr.e32.e_version != EV_CURRENT)
 268                         return (ctf_set_open_errno(errp, ECTF_ELFVERS));
 269 
 270                 if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS64) {
 271                         if (nbytes < sizeof (GElf_Ehdr))
 272                                 return (ctf_set_open_errno(errp, ECTF_FMT));
 273                 } else {
 274                         Elf32_Ehdr e32 = hdr.e32;
 275                         ehdr_to_gelf(&e32, &hdr.e64);
 276                 }
 277 
 278                 shnum = hdr.e64.e_shnum;
 279                 shstrndx = hdr.e64.e_shstrndx;
 280 
 281                 /* Extended ELF sections */
 282                 if ((shstrndx == SHN_XINDEX) || (shnum == 0)) {
 283                         if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) {
 284                                 Elf32_Shdr x32;
 285 
 286                                 if (pread64(fd, &x32, sizeof (x32),
 287                                     hdr.e64.e_shoff) != sizeof (x32))
 288                                         return (ctf_set_open_errno(errp,
 289                                             errno));
 290 
 291                                 shnum = x32.sh_size;
 292                                 shstrndx = x32.sh_link;
 293                         } else {
 294                                 Elf64_Shdr x64;
 295 
 296                                 if (pread64(fd, &x64, sizeof (x64),
 297                                     hdr.e64.e_shoff) != sizeof (x64))
 298                                         return (ctf_set_open_errno(errp,
 299                                             errno));
 300 
 301                                 shnum = x64.sh_size;
 302                                 shstrndx = x64.sh_link;
 303                         }
 304                 }
 305 
 306                 if (shstrndx >= shnum)
 307                         return (ctf_set_open_errno(errp, ECTF_CORRUPT));
 308 
 309                 nbytes = sizeof (GElf_Shdr) * shnum;

 310 
 311                 if ((sp = malloc(nbytes)) == NULL)
 312                         return (ctf_set_open_errno(errp, errno));
 313 
 314                 /*
 315                  * Read in and convert to GElf the array of Shdr structures
 316                  * from e_shoff so we can locate sections of interest.
 317                  */
 318                 if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) {
 319                         Elf32_Shdr *sp32;
 320 
 321                         nbytes = sizeof (Elf32_Shdr) * shnum;
 322 
 323                         if ((sp32 = malloc(nbytes)) == NULL || pread64(fd,
 324                             sp32, nbytes, hdr.e64.e_shoff) != nbytes) {
 325                                 free(sp);
 326                                 return (ctf_set_open_errno(errp, errno));
 327                         }
 328 
 329                         for (i = 0; i < shnum; i++)
 330                                 shdr_to_gelf(&sp32[i], &sp[i]);
 331 
 332                         free(sp32);
 333 
 334                 } else if (pread64(fd, sp, nbytes, hdr.e64.e_shoff) != nbytes) {
 335                         free(sp);
 336                         return (ctf_set_open_errno(errp, errno));
 337                 }
 338 
 339                 /*
 340                  * Now mmap the section header strings section so that we can
 341                  * perform string comparison on the section names.
 342                  */
 343                 strs_mapsz = sp[shstrndx].sh_size +
 344                     (sp[shstrndx].sh_offset & ~_PAGEMASK);
 345 
 346                 strs_map = mmap64(NULL, strs_mapsz, PROT_READ, MAP_PRIVATE,
 347                     fd, sp[shstrndx].sh_offset & _PAGEMASK);
 348 
 349                 strs = (const char *)strs_map +
 350                     (sp[shstrndx].sh_offset & ~_PAGEMASK);
 351 
 352                 if (strs_map == MAP_FAILED) {
 353                         free(sp);
 354                         return (ctf_set_open_errno(errp, ECTF_MMAP));
 355                 }
 356 
 357                 /*
 358                  * Iterate over the section header array looking for the CTF
 359                  * section and symbol table.  The strtab is linked to symtab.
 360                  */
 361                 for (i = 0; i < shnum; i++) {
 362                         const GElf_Shdr *shp = &sp[i];
 363                         const GElf_Shdr *lhp = &sp[shp->sh_link];
 364 
 365                         if (shp->sh_link >= shnum)
 366                                 continue; /* corrupt sh_link field */
 367 
 368                         if (shp->sh_name >= sp[shstrndx].sh_size ||
 369                             lhp->sh_name >= sp[shstrndx].sh_size)
 370                                 continue; /* corrupt sh_name field */
 371 
 372                         if (shp->sh_type == SHT_PROGBITS &&
 373                             strcmp(strs + shp->sh_name, _CTF_SECTION) == 0) {
 374                                 ctfsect.cts_name = strs + shp->sh_name;
 375                                 ctfsect.cts_type = shp->sh_type;
 376                                 ctfsect.cts_flags = shp->sh_flags;
 377                                 ctfsect.cts_size = shp->sh_size;
 378                                 ctfsect.cts_entsize = shp->sh_entsize;
 379                                 ctfsect.cts_offset = (off64_t)shp->sh_offset;
 380 
 381                         } else if (shp->sh_type == SHT_SYMTAB) {
 382                                 symsect.cts_name = strs + shp->sh_name;
 383                                 symsect.cts_type = shp->sh_type;
 384                                 symsect.cts_flags = shp->sh_flags;
 385                                 symsect.cts_size = shp->sh_size;
 386                                 symsect.cts_entsize = shp->sh_entsize;
 387                                 symsect.cts_offset = (off64_t)shp->sh_offset;
 388 
 389                                 strsect.cts_name = strs + lhp->sh_name;