17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5aa59c4cbSrsb * Common Development and Distribution License (the "License"). 6aa59c4cbSrsb * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22aa59c4cbSrsb * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h> 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <sys/elf.h> 317c478bd9Sstevel@tonic-gate #include <sys/errno.h> 327c478bd9Sstevel@tonic-gate #include <sys/file.h> 337c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 347c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 357c478bd9Sstevel@tonic-gate #include <sys/objfs.h> 367c478bd9Sstevel@tonic-gate #include <sys/objfs_impl.h> 377c478bd9Sstevel@tonic-gate #include <sys/stat.h> 387c478bd9Sstevel@tonic-gate #include <sys/systm.h> 397c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 40aa59c4cbSrsb #include <sys/vfs_opreg.h> 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate /* 437c478bd9Sstevel@tonic-gate * /system/object/<obj>/object 447c478bd9Sstevel@tonic-gate * 457c478bd9Sstevel@tonic-gate * This is an ELF file that contains information about data stored in the 467c478bd9Sstevel@tonic-gate * kernel. We use a special ELF file type, ET_SUNWPSEUDO, so that we can 477c478bd9Sstevel@tonic-gate * control which fields and sections have meaning. The file contains the 487c478bd9Sstevel@tonic-gate * following sections: 497c478bd9Sstevel@tonic-gate * 507c478bd9Sstevel@tonic-gate * .shstrtab Section header string table 517c478bd9Sstevel@tonic-gate * .SUNW_ctf CTF data 527c478bd9Sstevel@tonic-gate * .symtab Symbol table 537c478bd9Sstevel@tonic-gate * .strtab String table 547c478bd9Sstevel@tonic-gate * .text Text 557c478bd9Sstevel@tonic-gate * .data Data 567c478bd9Sstevel@tonic-gate * .bss BSS 577c478bd9Sstevel@tonic-gate * .filename Filename of module 587c478bd9Sstevel@tonic-gate * .info Private module info structure 597c478bd9Sstevel@tonic-gate * 607c478bd9Sstevel@tonic-gate * The .text, .data, and .bss sections are all marked SHT_NOBITS, and the data 617c478bd9Sstevel@tonic-gate * is not actually exported in the file for security reasons. The section 627c478bd9Sstevel@tonic-gate * headers do contain the address and size of the sections, which is needed by 637c478bd9Sstevel@tonic-gate * DTrace. The CTF data, symbol table, and string table are present only if 647c478bd9Sstevel@tonic-gate * they exist in the kernel. 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate typedef enum { 687c478bd9Sstevel@tonic-gate SECT_TYPE_DATA, 697c478bd9Sstevel@tonic-gate SECT_TYPE_SHSTRTAB, 707c478bd9Sstevel@tonic-gate SECT_TYPE_DUMMY, 717c478bd9Sstevel@tonic-gate SECT_TYPE_SYMTAB, 727c478bd9Sstevel@tonic-gate SECT_TYPE_STRTAB, 737c478bd9Sstevel@tonic-gate SECT_TYPE_FILENAME, 747c478bd9Sstevel@tonic-gate SECT_TYPE_INFO 757c478bd9Sstevel@tonic-gate } sect_type_t; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate typedef struct section_desc { 787c478bd9Sstevel@tonic-gate sect_type_t sect_id; 797c478bd9Sstevel@tonic-gate const char *sect_name; 807c478bd9Sstevel@tonic-gate uintptr_t sect_addr; 817c478bd9Sstevel@tonic-gate size_t sect_size; 827c478bd9Sstevel@tonic-gate int sect_type; 837c478bd9Sstevel@tonic-gate int sect_flags; 847c478bd9Sstevel@tonic-gate size_t sect_str; 857c478bd9Sstevel@tonic-gate int sect_link; 867c478bd9Sstevel@tonic-gate int sect_entsize; 877c478bd9Sstevel@tonic-gate int sect_align; 887c478bd9Sstevel@tonic-gate } section_desc_t; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate /* 917c478bd9Sstevel@tonic-gate * For data sections, 'addr' and 'size' refer to offsets within the module 927c478bd9Sstevel@tonic-gate * structure where we can find the address and size of the section. 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate #define SECT_DATA(name, addr, size, type, flags, align) \ 957c478bd9Sstevel@tonic-gate { SECT_TYPE_DATA, name, offsetof(struct module, addr), \ 967c478bd9Sstevel@tonic-gate offsetof(struct module, size), type, flags, 0, 0, 0, align } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * The dummy section is the initial section of the file. It is put into this 1007c478bd9Sstevel@tonic-gate * array only for convenience when reading the file. 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate #define SECT_DUMMY { SECT_TYPE_DUMMY, "", 0, 0, 0, 0, 0, 0, 0, 0 } 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* 1057c478bd9Sstevel@tonic-gate * The size of the symbol table and string table are not immediately available 1067c478bd9Sstevel@tonic-gate * as an offset into the module struct, so we have to create individual types 1077c478bd9Sstevel@tonic-gate * for each. 1087c478bd9Sstevel@tonic-gate */ 1097c478bd9Sstevel@tonic-gate #ifdef _LP64 1107c478bd9Sstevel@tonic-gate #define SECT_SYMTAB(name, type, flags) \ 1117c478bd9Sstevel@tonic-gate { SECT_TYPE_SYMTAB, name, offsetof(struct module, symtbl), 0, type, \ 1127c478bd9Sstevel@tonic-gate flags, 0, 0, sizeof (Elf64_Sym), sizeof (uint64_t) } 1137c478bd9Sstevel@tonic-gate #else 1147c478bd9Sstevel@tonic-gate #define SECT_SYMTAB(name, type, flags) \ 1157c478bd9Sstevel@tonic-gate { SECT_TYPE_SYMTAB, name, offsetof(struct module, symtbl), 0, type, \ 1167c478bd9Sstevel@tonic-gate flags, 0, 0, sizeof (Elf32_Sym), sizeof (uint32_t) } 1177c478bd9Sstevel@tonic-gate #endif 1187c478bd9Sstevel@tonic-gate #define SECT_STRTAB(name, type, flags) \ 1197c478bd9Sstevel@tonic-gate { SECT_TYPE_STRTAB, name, offsetof(struct module, strings), 0, type, \ 1207c478bd9Sstevel@tonic-gate flags, 0, 0, 0, 1 } 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* 1237c478bd9Sstevel@tonic-gate * The .shstrtab section is constructed when the module is first loaded. 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate #define SECT_SHSTRTAB(name, type, flags) \ 1267c478bd9Sstevel@tonic-gate { SECT_TYPE_SHSTRTAB, name, 0, 0, type, flags, 0, 0, 0, 1 } 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate /* 1297c478bd9Sstevel@tonic-gate * Generic module information (objfs_info_t) 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate #define SECT_INFO \ 1327c478bd9Sstevel@tonic-gate { SECT_TYPE_INFO, ".info", 0, 0, SHT_PROGBITS, 0, 0, 0, 0, \ 1337c478bd9Sstevel@tonic-gate sizeof (uint32_t) } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * Filename section. 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate #define SECT_FILENAME \ 1397c478bd9Sstevel@tonic-gate { SECT_TYPE_FILENAME, ".filename", 0, 0, SHT_PROGBITS, 0, 0, 0, 0, 1 } 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate static section_desc_t data_sections[] = { 1427c478bd9Sstevel@tonic-gate SECT_DUMMY, 1437c478bd9Sstevel@tonic-gate SECT_SHSTRTAB(".shstrtab", 1447c478bd9Sstevel@tonic-gate SHT_STRTAB, SHF_STRINGS), 1457c478bd9Sstevel@tonic-gate SECT_DATA(".SUNW_ctf", ctfdata, ctfsize, 1467c478bd9Sstevel@tonic-gate SHT_PROGBITS, 0, sizeof (uint64_t)), 1477c478bd9Sstevel@tonic-gate SECT_SYMTAB(".symtab", SHT_SYMTAB, 0), 1487c478bd9Sstevel@tonic-gate SECT_STRTAB(".strtab", SHT_STRTAB, SHF_STRINGS), 1497c478bd9Sstevel@tonic-gate SECT_DATA(".text", text, text_size, 1507c478bd9Sstevel@tonic-gate SHT_NOBITS, SHF_ALLOC | SHF_EXECINSTR, 0), 1517c478bd9Sstevel@tonic-gate SECT_DATA(".data", data, data_size, 1527c478bd9Sstevel@tonic-gate SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0), 1537c478bd9Sstevel@tonic-gate SECT_DATA(".bss", bss, bss_size, 1547c478bd9Sstevel@tonic-gate SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0), 1557c478bd9Sstevel@tonic-gate SECT_INFO, 1567c478bd9Sstevel@tonic-gate SECT_FILENAME 1577c478bd9Sstevel@tonic-gate }; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate #define NSECTIONS \ 1607c478bd9Sstevel@tonic-gate (sizeof (data_sections) / sizeof (section_desc_t)) 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate #ifdef _LP64 1637c478bd9Sstevel@tonic-gate #define SECTION_OFFSET(section) \ 1647c478bd9Sstevel@tonic-gate (sizeof (Elf64_Ehdr) + (section) * sizeof (Elf64_Shdr)) 1657c478bd9Sstevel@tonic-gate #else 1667c478bd9Sstevel@tonic-gate #define SECTION_OFFSET(section) \ 1677c478bd9Sstevel@tonic-gate (sizeof (Elf32_Ehdr) + (section) * sizeof (Elf32_Shdr)) 1687c478bd9Sstevel@tonic-gate #endif 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * Given a data node, returns the struct module appropriately locked. If the 1727c478bd9Sstevel@tonic-gate * object has been unloaded, or re-loaded since the file was first opened, this 1737c478bd9Sstevel@tonic-gate * function will return NULL. If successful, the caller must call 1747c478bd9Sstevel@tonic-gate * objfs_data_unlock(). 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate struct module * 1777c478bd9Sstevel@tonic-gate objfs_data_lock(vnode_t *vp) 1787c478bd9Sstevel@tonic-gate { 1797c478bd9Sstevel@tonic-gate objfs_datanode_t *dnode = vp->v_data; 1807c478bd9Sstevel@tonic-gate objfs_odirnode_t *odir = gfs_file_parent(vp)->v_data; 1817c478bd9Sstevel@tonic-gate struct modctl *mp = odir->objfs_odir_modctl; 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate (void) mod_hold_by_modctl(mp, MOD_WAIT_FOREVER | MOD_LOCK_NOT_HELD); 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate if (mp->mod_mp == NULL || 1867c478bd9Sstevel@tonic-gate dnode->objfs_data_gencount < mp->mod_gencount) { 1877c478bd9Sstevel@tonic-gate mod_release_mod(mp); 1887c478bd9Sstevel@tonic-gate return (NULL); 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate return (mp->mod_mp); 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate void 1957c478bd9Sstevel@tonic-gate objfs_data_unlock(vnode_t *vp) 1967c478bd9Sstevel@tonic-gate { 1977c478bd9Sstevel@tonic-gate objfs_odirnode_t *odir = gfs_file_parent(vp)->v_data; 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate mod_release_mod(odir->objfs_odir_modctl); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* 2047c478bd9Sstevel@tonic-gate * Called when the filesystem is first loaded. Creates and initializes the 2057c478bd9Sstevel@tonic-gate * section header string table, and fills in the sect_str members of the section 2067c478bd9Sstevel@tonic-gate * descriptors. This information could be encoded at compile-time, but this 2077c478bd9Sstevel@tonic-gate * way keeps the code more maintainable, as we don't have to worry about 2087c478bd9Sstevel@tonic-gate * duplicating information. 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate void 2117c478bd9Sstevel@tonic-gate objfs_data_init(void) 2127c478bd9Sstevel@tonic-gate { 2137c478bd9Sstevel@tonic-gate int i, shstrtab, strtab, symtab; 2147c478bd9Sstevel@tonic-gate size_t len = 0; 2157c478bd9Sstevel@tonic-gate section_desc_t *sect; 2167c478bd9Sstevel@tonic-gate char *strdata; 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate for (i = 0; i < NSECTIONS; i++) { 2197c478bd9Sstevel@tonic-gate sect = &data_sections[i]; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate ASSERT(sect->sect_align == 0 || ISP2(sect->sect_align)); 2227c478bd9Sstevel@tonic-gate ASSERT(sect->sect_align <= sizeof (uint64_t)); 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate len += strlen(sect->sect_name) + 1; 2257c478bd9Sstevel@tonic-gate if (strcmp(sect->sect_name, ".shstrtab") == 0) 2267c478bd9Sstevel@tonic-gate shstrtab = i; 2277c478bd9Sstevel@tonic-gate else if (strcmp(sect->sect_name, ".symtab") == 0) 2287c478bd9Sstevel@tonic-gate symtab = i; 2297c478bd9Sstevel@tonic-gate else if (strcmp(sect->sect_name, ".strtab") == 0) 2307c478bd9Sstevel@tonic-gate strtab = i; 2317c478bd9Sstevel@tonic-gate } 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate strdata = kmem_zalloc(len, KM_SLEEP); 2347c478bd9Sstevel@tonic-gate sect = &data_sections[shstrtab]; 2357c478bd9Sstevel@tonic-gate sect->sect_addr = (uintptr_t)strdata; 2367c478bd9Sstevel@tonic-gate sect->sect_size = len; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate len = 0; 2397c478bd9Sstevel@tonic-gate for (i = 0; i < NSECTIONS; i++) { 2407c478bd9Sstevel@tonic-gate sect = &data_sections[i]; 2417c478bd9Sstevel@tonic-gate sect->sect_str = len; 2427c478bd9Sstevel@tonic-gate bcopy(sect->sect_name, strdata + len, 2437c478bd9Sstevel@tonic-gate strlen(sect->sect_name) + 1); 2447c478bd9Sstevel@tonic-gate len += strlen(sect->sect_name) + 1; 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate if (strcmp(sect->sect_name, ".SUNW_ctf") == 0) 2477c478bd9Sstevel@tonic-gate sect->sect_link = symtab; 2487c478bd9Sstevel@tonic-gate else if (strcmp(sect->sect_name, ".symtab") == 0) 2497c478bd9Sstevel@tonic-gate sect->sect_link = strtab; 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * Given a section descriptor and module pointer, return the address of the 2557c478bd9Sstevel@tonic-gate * data. 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate static uintptr_t 2587c478bd9Sstevel@tonic-gate sect_addr(section_desc_t *sp, struct module *mp) 2597c478bd9Sstevel@tonic-gate { 2607c478bd9Sstevel@tonic-gate uintptr_t addr; 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate switch (sp->sect_id) { 2637c478bd9Sstevel@tonic-gate case SECT_TYPE_DUMMY: 2647c478bd9Sstevel@tonic-gate addr = 0; 2657c478bd9Sstevel@tonic-gate break; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate case SECT_TYPE_SHSTRTAB: 2687c478bd9Sstevel@tonic-gate addr = sp->sect_addr; 2697c478bd9Sstevel@tonic-gate break; 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate case SECT_TYPE_STRTAB: 2727c478bd9Sstevel@tonic-gate case SECT_TYPE_SYMTAB: 2737c478bd9Sstevel@tonic-gate case SECT_TYPE_DATA: 2747c478bd9Sstevel@tonic-gate addr = *((uintptr_t *)((char *)mp + sp->sect_addr)); 2757c478bd9Sstevel@tonic-gate break; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate case SECT_TYPE_FILENAME: 2787c478bd9Sstevel@tonic-gate addr = (uintptr_t)mp->filename; 2797c478bd9Sstevel@tonic-gate break; 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate case SECT_TYPE_INFO: 2827c478bd9Sstevel@tonic-gate addr = 1; /* This can be anything nonzero */ 2837c478bd9Sstevel@tonic-gate break; 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate return (addr); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* 2907c478bd9Sstevel@tonic-gate * Given a section descriptor and module pointer, return the size of the data. 2917c478bd9Sstevel@tonic-gate */ 2927c478bd9Sstevel@tonic-gate static size_t 2937c478bd9Sstevel@tonic-gate sect_size(section_desc_t *sp, struct module *mp) 2947c478bd9Sstevel@tonic-gate { 2957c478bd9Sstevel@tonic-gate size_t size; 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate switch (sp->sect_id) { 2987c478bd9Sstevel@tonic-gate case SECT_TYPE_DUMMY: 2997c478bd9Sstevel@tonic-gate size = 0; 3007c478bd9Sstevel@tonic-gate break; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate case SECT_TYPE_SHSTRTAB: 3037c478bd9Sstevel@tonic-gate size = sp->sect_size; 3047c478bd9Sstevel@tonic-gate break; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate case SECT_TYPE_DATA: 3077c478bd9Sstevel@tonic-gate size = *((size_t *)((char *)mp + sp->sect_size)); 3087c478bd9Sstevel@tonic-gate break; 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate case SECT_TYPE_SYMTAB: 3117c478bd9Sstevel@tonic-gate size = mp->symhdr->sh_size; 3127c478bd9Sstevel@tonic-gate break; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate case SECT_TYPE_STRTAB: 3157c478bd9Sstevel@tonic-gate size = mp->strhdr->sh_size; 3167c478bd9Sstevel@tonic-gate break; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate case SECT_TYPE_INFO: 3197c478bd9Sstevel@tonic-gate size = sizeof (objfs_info_t); 3207c478bd9Sstevel@tonic-gate break; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate case SECT_TYPE_FILENAME: 3237c478bd9Sstevel@tonic-gate if (mp->filename == NULL) 3247c478bd9Sstevel@tonic-gate size = 0; 3257c478bd9Sstevel@tonic-gate else 3267c478bd9Sstevel@tonic-gate size = strlen(mp->filename) + 1; 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate return (size); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /* 3337c478bd9Sstevel@tonic-gate * Given a section descriptor and module pointer, return 1 if the section has 3347c478bd9Sstevel@tonic-gate * valid data and should be included, 0 otherwise. 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate static int 3377c478bd9Sstevel@tonic-gate sect_valid(section_desc_t *sp, struct module *mp) 3387c478bd9Sstevel@tonic-gate { 3397c478bd9Sstevel@tonic-gate if (sp->sect_id == SECT_TYPE_DUMMY || 3407c478bd9Sstevel@tonic-gate sect_addr(sp, mp) != 0) 3417c478bd9Sstevel@tonic-gate return (1); 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate return (0); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate /* 3477c478bd9Sstevel@tonic-gate * Given a section descriptor and module pointer, return the offset into the 3487c478bd9Sstevel@tonic-gate * file where the data should be placed. 3497c478bd9Sstevel@tonic-gate */ 3507c478bd9Sstevel@tonic-gate static size_t 3517c478bd9Sstevel@tonic-gate data_offset(section_desc_t *sp, struct module *mp) 3527c478bd9Sstevel@tonic-gate { 3537c478bd9Sstevel@tonic-gate int i; 3547c478bd9Sstevel@tonic-gate size_t len; 3557c478bd9Sstevel@tonic-gate section_desc_t *cp; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate if (sp != NULL && mp != NULL && !sect_valid(sp, mp)) 3587c478bd9Sstevel@tonic-gate return (0); 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate #ifdef _LP64 3617c478bd9Sstevel@tonic-gate len = sizeof (Elf64_Ehdr); 3627c478bd9Sstevel@tonic-gate #else 3637c478bd9Sstevel@tonic-gate len = sizeof (Elf32_Ehdr); 3647c478bd9Sstevel@tonic-gate #endif 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate /* 3677c478bd9Sstevel@tonic-gate * Do a first pass to account for all the section headers. 3687c478bd9Sstevel@tonic-gate */ 3697c478bd9Sstevel@tonic-gate for (i = 0; i < NSECTIONS; i++) { 3707c478bd9Sstevel@tonic-gate if (sect_valid(&data_sections[i], mp)) { 3717c478bd9Sstevel@tonic-gate #ifdef _LP64 3727c478bd9Sstevel@tonic-gate len += sizeof (Elf64_Shdr); 3737c478bd9Sstevel@tonic-gate #else 3747c478bd9Sstevel@tonic-gate len += sizeof (Elf32_Shdr); 3757c478bd9Sstevel@tonic-gate #endif 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate /* 3807c478bd9Sstevel@tonic-gate * Add length of each section until we find the one we're looking for. 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate for (i = 0; i < NSECTIONS; i++) { 3837c478bd9Sstevel@tonic-gate cp = &data_sections[i]; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate /* 3867c478bd9Sstevel@tonic-gate * Align the section only if it's valid and contains data. When 3877c478bd9Sstevel@tonic-gate * searching for a specific section, align the section before 3887c478bd9Sstevel@tonic-gate * breaking out of the loop. 3897c478bd9Sstevel@tonic-gate */ 3907c478bd9Sstevel@tonic-gate if (sect_valid(cp, mp) && cp->sect_type != SHT_NOBITS) { 3917c478bd9Sstevel@tonic-gate if (cp->sect_align > 1) 3927c478bd9Sstevel@tonic-gate len = P2ROUNDUP(len, cp->sect_align); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate if (sp != cp) 3957c478bd9Sstevel@tonic-gate len += sect_size(cp, mp); 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate if (sp == cp) 3997c478bd9Sstevel@tonic-gate break; 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate return (len); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate /* 4067c478bd9Sstevel@tonic-gate * Given an index into the section table and a module pointer, returns the 4077c478bd9Sstevel@tonic-gate * data offset of the next section. 4087c478bd9Sstevel@tonic-gate */ 4097c478bd9Sstevel@tonic-gate static size_t 4107c478bd9Sstevel@tonic-gate next_offset(int idx, struct module *mp) 4117c478bd9Sstevel@tonic-gate { 4127c478bd9Sstevel@tonic-gate int i; 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate for (i = idx + 1; i < NSECTIONS; i++) { 4157c478bd9Sstevel@tonic-gate if (sect_valid(&data_sections[i], mp)) 4167c478bd9Sstevel@tonic-gate return (data_offset(&data_sections[i], mp)); 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate return (data_offset(NULL, mp)); 4207c478bd9Sstevel@tonic-gate } 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate /* 4237c478bd9Sstevel@tonic-gate * Given a module pointer, return the total size needed for the file. 4247c478bd9Sstevel@tonic-gate */ 4257c478bd9Sstevel@tonic-gate static size_t 4267c478bd9Sstevel@tonic-gate data_size(struct module *mp) 4277c478bd9Sstevel@tonic-gate { 4287c478bd9Sstevel@tonic-gate return (data_offset(NULL, mp)); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate /* 4327c478bd9Sstevel@tonic-gate * Returns the size needed for all the headers in the file. 4337c478bd9Sstevel@tonic-gate */ 4347c478bd9Sstevel@tonic-gate static size_t 4357c478bd9Sstevel@tonic-gate header_size(void) 4367c478bd9Sstevel@tonic-gate { 4377c478bd9Sstevel@tonic-gate return (data_offset(&data_sections[0], NULL)); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4417c478bd9Sstevel@tonic-gate vnode_t * 4427c478bd9Sstevel@tonic-gate objfs_create_data(vnode_t *pvp) 4437c478bd9Sstevel@tonic-gate { 4447c478bd9Sstevel@tonic-gate objfs_odirnode_t *onode = pvp->v_data; 4457c478bd9Sstevel@tonic-gate vnode_t *vp = gfs_file_create(sizeof (objfs_datanode_t), pvp, 4467c478bd9Sstevel@tonic-gate objfs_ops_data); 4477c478bd9Sstevel@tonic-gate objfs_datanode_t *dnode = vp->v_data; 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate dnode->objfs_data_gencount = onode->objfs_odir_modctl->mod_gencount; 4507c478bd9Sstevel@tonic-gate dnode->objfs_data_info.objfs_info_primary = 4517c478bd9Sstevel@tonic-gate onode->objfs_odir_modctl->mod_prim; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate return (vp); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4577c478bd9Sstevel@tonic-gate static int 458*da6c28aaSamw objfs_data_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, 459*da6c28aaSamw caller_context_t *ct) 4607c478bd9Sstevel@tonic-gate { 4617c478bd9Sstevel@tonic-gate struct module *mp; 4627c478bd9Sstevel@tonic-gate timestruc_t now; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate if ((mp = objfs_data_lock(vp)) == NULL) 4657c478bd9Sstevel@tonic-gate return (EIO); 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate vap->va_type = VREG; 4687c478bd9Sstevel@tonic-gate vap->va_mode = S_IRUSR | S_IRGRP | S_IROTH; 4697c478bd9Sstevel@tonic-gate vap->va_nodeid = gfs_file_inode(vp); 4707c478bd9Sstevel@tonic-gate vap->va_nlink = 1; 4717c478bd9Sstevel@tonic-gate vap->va_size = data_size(mp); 4727c478bd9Sstevel@tonic-gate gethrestime(&now); 4737c478bd9Sstevel@tonic-gate vap->va_atime = vap->va_ctime = vap->va_mtime = now; 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate (void) objfs_common_getattr(vp, vap); 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate objfs_data_unlock(vp); 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate return (0); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4837c478bd9Sstevel@tonic-gate static int 484*da6c28aaSamw objfs_data_access(vnode_t *vp, int mode, int flags, cred_t *cr, 485*da6c28aaSamw caller_context_t *ct) 4867c478bd9Sstevel@tonic-gate { 4877c478bd9Sstevel@tonic-gate if (mode & (VWRITE|VEXEC)) 4887c478bd9Sstevel@tonic-gate return (EACCES); 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate return (0); 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* ARGSUSED */ 4947c478bd9Sstevel@tonic-gate int 495*da6c28aaSamw objfs_data_open(vnode_t **cpp, int flag, cred_t *cr, 496*da6c28aaSamw caller_context_t *ct) 4977c478bd9Sstevel@tonic-gate { 4987c478bd9Sstevel@tonic-gate if (flag & FWRITE) 4997c478bd9Sstevel@tonic-gate return (EINVAL); 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate return (0); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate /* 5057c478bd9Sstevel@tonic-gate * Iterate over all symbols in the table and output each one individually, 5067c478bd9Sstevel@tonic-gate * converting st_shndx to SHN_ABS for each symbol. 5077c478bd9Sstevel@tonic-gate */ 5087c478bd9Sstevel@tonic-gate static int 5097c478bd9Sstevel@tonic-gate read_symtab(void *addr, size_t size, off_t offset, uio_t *uio) 5107c478bd9Sstevel@tonic-gate { 5117c478bd9Sstevel@tonic-gate #ifdef _LP64 5127c478bd9Sstevel@tonic-gate Elf64_Sym sym, *symtab; 5137c478bd9Sstevel@tonic-gate #else 5147c478bd9Sstevel@tonic-gate Elf32_Sym sym, *symtab; 5157c478bd9Sstevel@tonic-gate #endif 5167c478bd9Sstevel@tonic-gate off_t index; 5177c478bd9Sstevel@tonic-gate int error; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate symtab = addr; 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate if (offset % sizeof (sym) != 0) { 5227c478bd9Sstevel@tonic-gate /* 5237c478bd9Sstevel@tonic-gate * Be careful with the first symbol, as it is not 5247c478bd9Sstevel@tonic-gate * symbol-aligned. 5257c478bd9Sstevel@tonic-gate */ 5267c478bd9Sstevel@tonic-gate off_t partial = offset % sizeof (sym); 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate index = offset / sizeof (sym); 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate sym = symtab[index]; 5317c478bd9Sstevel@tonic-gate if (sym.st_shndx != SHN_UNDEF) 5327c478bd9Sstevel@tonic-gate sym.st_shndx = SHN_ABS; 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate if ((error = uiomove((char *)&sym + partial, 5357c478bd9Sstevel@tonic-gate sizeof (sym) - partial, UIO_READ, uio)) != 0 || 5367c478bd9Sstevel@tonic-gate uio->uio_resid <= 0) 5377c478bd9Sstevel@tonic-gate return (error); 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate offset = (index + 1) * sizeof (sym); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate ASSERT(size % sizeof (sym) == 0); 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate for (index = offset / sizeof (sym); index < size / sizeof (sym); 5457c478bd9Sstevel@tonic-gate index++) { 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate sym = symtab[index]; 5487c478bd9Sstevel@tonic-gate if (sym.st_shndx != SHN_UNDEF) 5497c478bd9Sstevel@tonic-gate sym.st_shndx = SHN_ABS; 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate if ((error = uiomove((char *)&sym, sizeof (sym), UIO_READ, 5527c478bd9Sstevel@tonic-gate uio)) != 0 || uio->uio_resid <= 0) 5537c478bd9Sstevel@tonic-gate return (error); 5547c478bd9Sstevel@tonic-gate } 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate return (0); 5577c478bd9Sstevel@tonic-gate } 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* ARGSUSED */ 5607c478bd9Sstevel@tonic-gate static int 5617c478bd9Sstevel@tonic-gate objfs_data_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, 5627c478bd9Sstevel@tonic-gate caller_context_t *ct) 5637c478bd9Sstevel@tonic-gate { 5647c478bd9Sstevel@tonic-gate int error = 0; 5657c478bd9Sstevel@tonic-gate objfs_datanode_t *dnode = vp->v_data; 5667c478bd9Sstevel@tonic-gate struct module *mp; 5677c478bd9Sstevel@tonic-gate off_t off; 5687c478bd9Sstevel@tonic-gate #ifdef _LP64 5697c478bd9Sstevel@tonic-gate Elf64_Shdr shdr; 5707c478bd9Sstevel@tonic-gate #else 5717c478bd9Sstevel@tonic-gate Elf32_Shdr shdr; 5727c478bd9Sstevel@tonic-gate #endif 5737c478bd9Sstevel@tonic-gate int i, j; 5747c478bd9Sstevel@tonic-gate section_desc_t *sp; 5757c478bd9Sstevel@tonic-gate void *addr; 5767c478bd9Sstevel@tonic-gate int transidx[NSECTIONS]; 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate if ((mp = objfs_data_lock(vp)) == NULL) 5797c478bd9Sstevel@tonic-gate return (ENOENT); 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate if (uio->uio_resid <= 0 || uio->uio_offset >= data_size(mp)) 5827c478bd9Sstevel@tonic-gate goto error; 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate /* 5857c478bd9Sstevel@tonic-gate * Construct an array to translate from a generic section header index 5867c478bd9Sstevel@tonic-gate * to an index specific for this object. 5877c478bd9Sstevel@tonic-gate */ 5887c478bd9Sstevel@tonic-gate for (i = 0, j = 0; i < NSECTIONS; i++) { 5897c478bd9Sstevel@tonic-gate transidx[i] = j; 5907c478bd9Sstevel@tonic-gate if (sect_valid(&data_sections[i], mp)) 5917c478bd9Sstevel@tonic-gate j++; 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate /* 5967c478bd9Sstevel@tonic-gate * Check to see if we're in the Elf header 5977c478bd9Sstevel@tonic-gate */ 5987c478bd9Sstevel@tonic-gate if (uio->uio_loffset < SECTION_OFFSET(0)) { 5997c478bd9Sstevel@tonic-gate #ifdef _LP64 6007c478bd9Sstevel@tonic-gate Elf64_Ehdr ehdr; 6017c478bd9Sstevel@tonic-gate #else 6027c478bd9Sstevel@tonic-gate Elf32_Ehdr ehdr; 6037c478bd9Sstevel@tonic-gate #endif 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate bzero(&ehdr, sizeof (ehdr)); 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate bcopy(ELFMAG, ehdr.e_ident, SELFMAG); 6087c478bd9Sstevel@tonic-gate #ifdef _BIG_ENDIAN 6097c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_DATA] = ELFDATA2MSB; 6107c478bd9Sstevel@tonic-gate #else 6117c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_DATA] = ELFDATA2LSB; 6127c478bd9Sstevel@tonic-gate #endif 6137c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_VERSION] = EV_CURRENT; 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate #ifdef _LP64 6167c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_CLASS] = ELFCLASS64; 6177c478bd9Sstevel@tonic-gate ehdr.e_type = ELFCLASS64; 6187c478bd9Sstevel@tonic-gate ehdr.e_ehsize = sizeof (Elf64_Ehdr); 6197c478bd9Sstevel@tonic-gate ehdr.e_phentsize = sizeof (Elf64_Phdr); 6207c478bd9Sstevel@tonic-gate ehdr.e_shentsize = sizeof (Elf64_Shdr); 6217c478bd9Sstevel@tonic-gate #else 6227c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_CLASS] = ELFCLASS32; 6237c478bd9Sstevel@tonic-gate ehdr.e_type = ELFCLASS32; 6247c478bd9Sstevel@tonic-gate ehdr.e_ehsize = sizeof (Elf32_Ehdr); 6257c478bd9Sstevel@tonic-gate ehdr.e_phentsize = sizeof (Elf32_Phdr); 6267c478bd9Sstevel@tonic-gate ehdr.e_shentsize = sizeof (Elf32_Shdr); 6277c478bd9Sstevel@tonic-gate #endif 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate #ifdef __sparc 6307c478bd9Sstevel@tonic-gate #ifdef __sparcv9 6317c478bd9Sstevel@tonic-gate ehdr.e_machine = EM_SPARCV9; 6327c478bd9Sstevel@tonic-gate #else 6337c478bd9Sstevel@tonic-gate ehdr.e_machine = EM_SPARC; 6347c478bd9Sstevel@tonic-gate #endif 6357c478bd9Sstevel@tonic-gate #elif defined(__amd64) 6367c478bd9Sstevel@tonic-gate ehdr.e_machine = EM_AMD64; 6377c478bd9Sstevel@tonic-gate #else 6387c478bd9Sstevel@tonic-gate ehdr.e_machine = EM_386; 6397c478bd9Sstevel@tonic-gate #endif 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate ehdr.e_version = EV_CURRENT; 6427c478bd9Sstevel@tonic-gate ehdr.e_type = ET_SUNWPSEUDO; 6437c478bd9Sstevel@tonic-gate ehdr.e_shnum = 0; 6447c478bd9Sstevel@tonic-gate ehdr.e_shoff = SECTION_OFFSET(0); 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate for (i = 0; i < NSECTIONS; i++) { 6477c478bd9Sstevel@tonic-gate if (strcmp(data_sections[i].sect_name, 6487c478bd9Sstevel@tonic-gate ".shstrtab") == 0) 6497c478bd9Sstevel@tonic-gate ehdr.e_shstrndx = transidx[i]; 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate if (sect_valid(&data_sections[i], mp)) 6527c478bd9Sstevel@tonic-gate ehdr.e_shnum++; 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate if ((error = uiomove((char *)&ehdr + uio->uio_loffset, 6567c478bd9Sstevel@tonic-gate sizeof (ehdr) - uio->uio_loffset, UIO_READ, uio)) != 0 || 6577c478bd9Sstevel@tonic-gate uio->uio_resid <= 0) 6587c478bd9Sstevel@tonic-gate goto error; 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate /* 6627c478bd9Sstevel@tonic-gate * Go through and construct section headers for each section. 6637c478bd9Sstevel@tonic-gate */ 6647c478bd9Sstevel@tonic-gate j = 0; 6657c478bd9Sstevel@tonic-gate for (i = 0; i < NSECTIONS; i++) { 6667c478bd9Sstevel@tonic-gate sp = &data_sections[i]; 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate if (!sect_valid(sp, mp)) 6697c478bd9Sstevel@tonic-gate continue; 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate if (uio->uio_loffset < SECTION_OFFSET(j+1)) { 6727c478bd9Sstevel@tonic-gate shdr.sh_link = transidx[sp->sect_link]; 6737c478bd9Sstevel@tonic-gate shdr.sh_entsize = sp->sect_entsize; 6747c478bd9Sstevel@tonic-gate shdr.sh_info = 0; 6757c478bd9Sstevel@tonic-gate shdr.sh_name = sp->sect_str; 6767c478bd9Sstevel@tonic-gate shdr.sh_type = sp->sect_type; 6777c478bd9Sstevel@tonic-gate shdr.sh_flags = sp->sect_flags; 6787c478bd9Sstevel@tonic-gate shdr.sh_addr = sect_addr(sp, mp); 6797c478bd9Sstevel@tonic-gate shdr.sh_offset = data_offset(sp, mp); 6807c478bd9Sstevel@tonic-gate shdr.sh_size = sect_size(sp, mp); 6817c478bd9Sstevel@tonic-gate shdr.sh_addralign = sp->sect_align; 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate off = uio->uio_loffset - SECTION_OFFSET(j); 6847c478bd9Sstevel@tonic-gate if ((error = uiomove((char *)&shdr + off, 6857c478bd9Sstevel@tonic-gate sizeof (shdr) - off, UIO_READ, uio)) != 0 || 6867c478bd9Sstevel@tonic-gate uio->uio_resid <= 0) 6877c478bd9Sstevel@tonic-gate goto error; 6887c478bd9Sstevel@tonic-gate } 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate j++; 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate /* 6947c478bd9Sstevel@tonic-gate * Output the data for each section 6957c478bd9Sstevel@tonic-gate */ 6967c478bd9Sstevel@tonic-gate for (i = 0; i < NSECTIONS; i++) { 6977c478bd9Sstevel@tonic-gate size_t nextoff; 6987c478bd9Sstevel@tonic-gate sp = &data_sections[i]; 6997c478bd9Sstevel@tonic-gate nextoff = next_offset(i, mp); 7007c478bd9Sstevel@tonic-gate if (sect_valid(sp, mp) && sp->sect_type != SHT_NOBITS && 7017c478bd9Sstevel@tonic-gate uio->uio_loffset < nextoff) { 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate if (sp->sect_id == SECT_TYPE_INFO) 7047c478bd9Sstevel@tonic-gate addr = &dnode->objfs_data_info; 7057c478bd9Sstevel@tonic-gate else 7067c478bd9Sstevel@tonic-gate addr = (void *)sect_addr(sp, mp); 7077c478bd9Sstevel@tonic-gate off = uio->uio_loffset - data_offset(sp, mp); 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate /* 7107c478bd9Sstevel@tonic-gate * The symtab requires special processing to convert 7117c478bd9Sstevel@tonic-gate * the st_shndx field to SHN_ABS. Otherwise, simply 7127c478bd9Sstevel@tonic-gate * copy the data in bulk. 7137c478bd9Sstevel@tonic-gate */ 7147c478bd9Sstevel@tonic-gate if (sp->sect_id == SECT_TYPE_SYMTAB) 7157c478bd9Sstevel@tonic-gate error = read_symtab(addr, sect_size(sp, mp), 7167c478bd9Sstevel@tonic-gate off, uio); 7177c478bd9Sstevel@tonic-gate else 7187c478bd9Sstevel@tonic-gate error = uiomove((char *)addr + off, 7197c478bd9Sstevel@tonic-gate sect_size(sp, mp) - off, UIO_READ, uio); 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate if (error != 0 || uio->uio_resid <= 0) 7227c478bd9Sstevel@tonic-gate goto error; 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate /* 7257c478bd9Sstevel@tonic-gate * If the next section needs to be aligned, pad out with 7267c478bd9Sstevel@tonic-gate * zeroes. 7277c478bd9Sstevel@tonic-gate */ 7287c478bd9Sstevel@tonic-gate if (uio->uio_loffset < nextoff) { 7297c478bd9Sstevel@tonic-gate uint64_t padding = 0; 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate ASSERT(nextoff - uio->uio_loffset < 7327c478bd9Sstevel@tonic-gate sizeof (uint64_t)); 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate if ((error = uiomove(&padding, 7357c478bd9Sstevel@tonic-gate nextoff - uio->uio_loffset, UIO_READ, 7367c478bd9Sstevel@tonic-gate uio)) != 0 || uio->uio_resid <= 0) 7377c478bd9Sstevel@tonic-gate goto error; 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate } 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate error: 7447c478bd9Sstevel@tonic-gate objfs_data_unlock(vp); 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate return (error); 7477c478bd9Sstevel@tonic-gate } 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate /* ARGSUSED */ 7507c478bd9Sstevel@tonic-gate static int 751*da6c28aaSamw objfs_data_seek(vnode_t *vp, offset_t off, offset_t *offp, 752*da6c28aaSamw caller_context_t *ct) 7537c478bd9Sstevel@tonic-gate { 7547c478bd9Sstevel@tonic-gate return (0); 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate const fs_operation_def_t objfs_tops_data[] = { 758aa59c4cbSrsb { VOPNAME_OPEN, { .vop_open = objfs_data_open } }, 759aa59c4cbSrsb { VOPNAME_CLOSE, { .vop_close = objfs_common_close } }, 760aa59c4cbSrsb { VOPNAME_IOCTL, { .error = fs_inval } }, 761aa59c4cbSrsb { VOPNAME_GETATTR, { .vop_getattr = objfs_data_getattr } }, 762aa59c4cbSrsb { VOPNAME_ACCESS, { .vop_access = objfs_data_access } }, 763aa59c4cbSrsb { VOPNAME_INACTIVE, { .vop_inactive = gfs_vop_inactive } }, 764aa59c4cbSrsb { VOPNAME_READ, { .vop_read = objfs_data_read } }, 765aa59c4cbSrsb { VOPNAME_SEEK, { .vop_seek = objfs_data_seek } }, 766aa59c4cbSrsb { VOPNAME_MAP, { .vop_map = gfs_vop_map } }, 7677c478bd9Sstevel@tonic-gate { NULL } 7687c478bd9Sstevel@tonic-gate }; 769