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.
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.
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]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/fs_subr.h>
31 #include <sys/errno.h>
35 #include <sys/objfs.h>
36 #include <sys/objfs_impl.h>
38 #include <sys/systm.h>
39 #include <sys/sysmacros.h>
42 static const struct vnodeops objfs_ops_data
;
45 * /system/object/<obj>/object
47 * This is an ELF file that contains information about data stored in the
48 * kernel. We use a special ELF file type, ET_SUNWPSEUDO, so that we can
49 * control which fields and sections have meaning. The file contains the
52 * .shstrtab Section header string table
54 * .symtab Symbol table
55 * .strtab String table
59 * .filename Filename of module
60 * .info Private module info structure
62 * The .text, .data, and .bss sections are all marked SHT_NOBITS, and the data
63 * is not actually exported in the file for security reasons. The section
64 * headers do contain the address and size of the sections, which is needed by
65 * DTrace. The CTF data, symbol table, and string table are present only if
66 * they exist in the kernel.
79 typedef struct section_desc
{
81 const char *sect_name
;
93 * For data sections, 'addr' and 'size' refer to offsets within the module
94 * structure where we can find the address and size of the section.
96 #define SECT_DATA(name, addr, size, type, flags, align) \
97 { SECT_TYPE_DATA, name, offsetof(struct module, addr), \
98 offsetof(struct module, size), type, flags, 0, 0, 0, align }
101 * The dummy section is the initial section of the file. It is put into this
102 * array only for convenience when reading the file.
104 #define SECT_DUMMY { SECT_TYPE_DUMMY, "", 0, 0, 0, 0, 0, 0, 0, 0 }
107 * The size of the symbol table and string table are not immediately available
108 * as an offset into the module struct, so we have to create individual types
112 #define SECT_SYMTAB(name, type, flags) \
113 { SECT_TYPE_SYMTAB, name, offsetof(struct module, symtbl), 0, type, \
114 flags, 0, 0, sizeof (Elf64_Sym), sizeof (uint64_t) }
116 #define SECT_SYMTAB(name, type, flags) \
117 { SECT_TYPE_SYMTAB, name, offsetof(struct module, symtbl), 0, type, \
118 flags, 0, 0, sizeof (Elf32_Sym), sizeof (uint32_t) }
120 #define SECT_STRTAB(name, type, flags) \
121 { SECT_TYPE_STRTAB, name, offsetof(struct module, strings), 0, type, \
125 * The .shstrtab section is constructed when the module is first loaded.
127 #define SECT_SHSTRTAB(name, type, flags) \
128 { SECT_TYPE_SHSTRTAB, name, 0, 0, type, flags, 0, 0, 0, 1 }
131 * Generic module information (objfs_info_t)
134 { SECT_TYPE_INFO, ".info", 0, 0, SHT_PROGBITS, 0, 0, 0, 0, \
140 #define SECT_FILENAME \
141 { SECT_TYPE_FILENAME, ".filename", 0, 0, SHT_PROGBITS, 0, 0, 0, 0, 1 }
143 static section_desc_t data_sections
[] = {
145 SECT_SHSTRTAB(".shstrtab",
146 SHT_STRTAB
, SHF_STRINGS
),
147 SECT_DATA(".SUNW_ctf", ctfdata
, ctfsize
,
148 SHT_PROGBITS
, 0, sizeof (uint64_t)),
149 SECT_SYMTAB(".symtab", SHT_SYMTAB
, 0),
150 SECT_STRTAB(".strtab", SHT_STRTAB
, SHF_STRINGS
),
151 SECT_DATA(".text", text
, text_size
,
152 SHT_NOBITS
, SHF_ALLOC
| SHF_EXECINSTR
, 0),
153 SECT_DATA(".data", data
, data_size
,
154 SHT_NOBITS
, SHF_WRITE
| SHF_ALLOC
, 0),
155 SECT_DATA(".bss", bss
, bss_size
,
156 SHT_NOBITS
, SHF_WRITE
| SHF_ALLOC
, 0),
162 (sizeof (data_sections) / sizeof (section_desc_t))
165 #define SECTION_OFFSET(section) \
166 (sizeof (Elf64_Ehdr) + (section) * sizeof (Elf64_Shdr))
168 #define SECTION_OFFSET(section) \
169 (sizeof (Elf32_Ehdr) + (section) * sizeof (Elf32_Shdr))
173 * Given a data node, returns the struct module appropriately locked. If the
174 * object has been unloaded, or re-loaded since the file was first opened, this
175 * function will return NULL. If successful, the caller must call
176 * objfs_data_unlock().
179 objfs_data_lock(vnode_t
*vp
)
181 objfs_datanode_t
*dnode
= vp
->v_data
;
182 objfs_odirnode_t
*odir
= gfs_file_parent(vp
)->v_data
;
183 struct modctl
*mp
= odir
->objfs_odir_modctl
;
185 (void) mod_hold_by_modctl(mp
, MOD_WAIT_FOREVER
| MOD_LOCK_NOT_HELD
);
187 if (mp
->mod_mp
== NULL
||
188 dnode
->objfs_data_gencount
< mp
->mod_gencount
) {
197 objfs_data_unlock(vnode_t
*vp
)
199 objfs_odirnode_t
*odir
= gfs_file_parent(vp
)->v_data
;
201 mod_release_mod(odir
->objfs_odir_modctl
);
206 * Called when the filesystem is first loaded. Creates and initializes the
207 * section header string table, and fills in the sect_str members of the section
208 * descriptors. This information could be encoded at compile-time, but this
209 * way keeps the code more maintainable, as we don't have to worry about
210 * duplicating information.
213 objfs_data_init(void)
215 int i
, shstrtab
, strtab
, symtab
;
217 section_desc_t
*sect
;
220 for (i
= 0; i
< NSECTIONS
; i
++) {
221 sect
= &data_sections
[i
];
223 ASSERT(sect
->sect_align
== 0 || ISP2(sect
->sect_align
));
224 ASSERT(sect
->sect_align
<= sizeof (uint64_t));
226 len
+= strlen(sect
->sect_name
) + 1;
227 if (strcmp(sect
->sect_name
, ".shstrtab") == 0)
229 else if (strcmp(sect
->sect_name
, ".symtab") == 0)
231 else if (strcmp(sect
->sect_name
, ".strtab") == 0)
235 strdata
= kmem_zalloc(len
, KM_SLEEP
);
236 sect
= &data_sections
[shstrtab
];
237 sect
->sect_addr
= (uintptr_t)strdata
;
238 sect
->sect_size
= len
;
241 for (i
= 0; i
< NSECTIONS
; i
++) {
242 sect
= &data_sections
[i
];
243 sect
->sect_str
= len
;
244 bcopy(sect
->sect_name
, strdata
+ len
,
245 strlen(sect
->sect_name
) + 1);
246 len
+= strlen(sect
->sect_name
) + 1;
248 if (strcmp(sect
->sect_name
, ".SUNW_ctf") == 0)
249 sect
->sect_link
= symtab
;
250 else if (strcmp(sect
->sect_name
, ".symtab") == 0)
251 sect
->sect_link
= strtab
;
256 * Given a section descriptor and module pointer, return the address of the
260 sect_addr(section_desc_t
*sp
, struct module
*mp
)
264 switch (sp
->sect_id
) {
265 case SECT_TYPE_DUMMY
:
269 case SECT_TYPE_SHSTRTAB
:
270 addr
= sp
->sect_addr
;
273 case SECT_TYPE_STRTAB
:
274 case SECT_TYPE_SYMTAB
:
276 addr
= *((uintptr_t *)((char *)mp
+ sp
->sect_addr
));
279 case SECT_TYPE_FILENAME
:
280 addr
= (uintptr_t)mp
->filename
;
284 addr
= 1; /* This can be anything nonzero */
292 * Given a section descriptor and module pointer, return the size of the data.
295 sect_size(section_desc_t
*sp
, struct module
*mp
)
299 switch (sp
->sect_id
) {
300 case SECT_TYPE_DUMMY
:
304 case SECT_TYPE_SHSTRTAB
:
305 size
= sp
->sect_size
;
309 size
= *((size_t *)((char *)mp
+ sp
->sect_size
));
312 case SECT_TYPE_SYMTAB
:
313 size
= mp
->symhdr
->sh_size
;
316 case SECT_TYPE_STRTAB
:
317 size
= mp
->strhdr
->sh_size
;
321 size
= sizeof (objfs_info_t
);
324 case SECT_TYPE_FILENAME
:
325 if (mp
->filename
== NULL
)
328 size
= strlen(mp
->filename
) + 1;
335 * Given a section descriptor and module pointer, return 1 if the section has
336 * valid data and should be included, 0 otherwise.
339 sect_valid(section_desc_t
*sp
, struct module
*mp
)
341 if (sp
->sect_id
== SECT_TYPE_DUMMY
||
342 sect_addr(sp
, mp
) != 0)
349 * Given a section descriptor and module pointer, return the offset into the
350 * file where the data should be placed.
353 data_offset(section_desc_t
*sp
, struct module
*mp
)
359 if (sp
!= NULL
&& mp
!= NULL
&& !sect_valid(sp
, mp
))
363 len
= sizeof (Elf64_Ehdr
);
365 len
= sizeof (Elf32_Ehdr
);
369 * Do a first pass to account for all the section headers.
371 for (i
= 0; i
< NSECTIONS
; i
++) {
372 if (sect_valid(&data_sections
[i
], mp
)) {
374 len
+= sizeof (Elf64_Shdr
);
376 len
+= sizeof (Elf32_Shdr
);
382 * Add length of each section until we find the one we're looking for.
384 for (i
= 0; i
< NSECTIONS
; i
++) {
385 cp
= &data_sections
[i
];
388 * Align the section only if it's valid and contains data. When
389 * searching for a specific section, align the section before
390 * breaking out of the loop.
392 if (sect_valid(cp
, mp
) && cp
->sect_type
!= SHT_NOBITS
) {
393 if (cp
->sect_align
> 1)
394 len
= P2ROUNDUP(len
, cp
->sect_align
);
397 len
+= sect_size(cp
, mp
);
408 * Given an index into the section table and a module pointer, returns the
409 * data offset of the next section.
412 next_offset(int idx
, struct module
*mp
)
416 for (i
= idx
+ 1; i
< NSECTIONS
; i
++) {
417 if (sect_valid(&data_sections
[i
], mp
))
418 return (data_offset(&data_sections
[i
], mp
));
421 return (data_offset(NULL
, mp
));
425 * Given a module pointer, return the total size needed for the file.
428 data_size(struct module
*mp
)
430 return (data_offset(NULL
, mp
));
434 * Returns the size needed for all the headers in the file.
439 return (data_offset(&data_sections
[0], NULL
));
444 objfs_create_data(vnode_t
*pvp
)
446 objfs_odirnode_t
*onode
= pvp
->v_data
;
447 vnode_t
*vp
= gfs_file_create(sizeof (objfs_datanode_t
), pvp
,
449 objfs_datanode_t
*dnode
= vp
->v_data
;
451 dnode
->objfs_data_gencount
= onode
->objfs_odir_modctl
->mod_gencount
;
452 dnode
->objfs_data_info
.objfs_info_primary
=
453 onode
->objfs_odir_modctl
->mod_prim
;
460 objfs_data_getattr(vnode_t
*vp
, vattr_t
*vap
, int flags
, cred_t
*cr
,
461 caller_context_t
*ct
)
466 if ((mp
= objfs_data_lock(vp
)) == NULL
)
470 vap
->va_mode
= S_IRUSR
| S_IRGRP
| S_IROTH
;
471 vap
->va_nodeid
= gfs_file_inode(vp
);
473 vap
->va_size
= data_size(mp
);
475 vap
->va_atime
= vap
->va_ctime
= vap
->va_mtime
= now
;
477 (void) objfs_common_getattr(vp
, vap
);
479 objfs_data_unlock(vp
);
486 objfs_data_access(vnode_t
*vp
, int mode
, int flags
, cred_t
*cr
,
487 caller_context_t
*ct
)
489 if (mode
& (VWRITE
|VEXEC
))
497 objfs_data_open(vnode_t
**cpp
, int flag
, cred_t
*cr
,
498 caller_context_t
*ct
)
507 * Iterate over all symbols in the table and output each one individually,
508 * converting st_shndx to SHN_ABS for each symbol.
511 read_symtab(void *addr
, size_t size
, off_t offset
, uio_t
*uio
)
514 Elf64_Sym sym
, *symtab
;
516 Elf32_Sym sym
, *symtab
;
523 if (offset
% sizeof (sym
) != 0) {
525 * Be careful with the first symbol, as it is not
528 off_t partial
= offset
% sizeof (sym
);
530 index
= offset
/ sizeof (sym
);
533 if (sym
.st_shndx
!= SHN_UNDEF
)
534 sym
.st_shndx
= SHN_ABS
;
536 if ((error
= uiomove((char *)&sym
+ partial
,
537 sizeof (sym
) - partial
, UIO_READ
, uio
)) != 0 ||
541 offset
= (index
+ 1) * sizeof (sym
);
544 ASSERT(size
% sizeof (sym
) == 0);
546 for (index
= offset
/ sizeof (sym
); index
< size
/ sizeof (sym
);
550 if (sym
.st_shndx
!= SHN_UNDEF
)
551 sym
.st_shndx
= SHN_ABS
;
553 if ((error
= uiomove((char *)&sym
, sizeof (sym
), UIO_READ
,
554 uio
)) != 0 || uio
->uio_resid
<= 0)
563 objfs_data_read(vnode_t
*vp
, uio_t
*uio
, int ioflag
, cred_t
*cr
,
564 caller_context_t
*ct
)
567 objfs_datanode_t
*dnode
= vp
->v_data
;
578 int transidx
[NSECTIONS
];
580 if ((mp
= objfs_data_lock(vp
)) == NULL
)
583 if (uio
->uio_resid
<= 0 || uio
->uio_offset
>= data_size(mp
))
587 * Construct an array to translate from a generic section header index
588 * to an index specific for this object.
590 for (i
= 0, j
= 0; i
< NSECTIONS
; i
++) {
592 if (sect_valid(&data_sections
[i
], mp
))
598 * Check to see if we're in the Elf header
600 if (uio
->uio_loffset
< SECTION_OFFSET(0)) {
607 bzero(&ehdr
, sizeof (ehdr
));
609 bcopy(ELFMAG
, ehdr
.e_ident
, SELFMAG
);
611 ehdr
.e_ident
[EI_DATA
] = ELFDATA2MSB
;
613 ehdr
.e_ident
[EI_DATA
] = ELFDATA2LSB
;
615 ehdr
.e_ident
[EI_VERSION
] = EV_CURRENT
;
618 ehdr
.e_ident
[EI_CLASS
] = ELFCLASS64
;
619 ehdr
.e_type
= ELFCLASS64
;
620 ehdr
.e_ehsize
= sizeof (Elf64_Ehdr
);
621 ehdr
.e_phentsize
= sizeof (Elf64_Phdr
);
622 ehdr
.e_shentsize
= sizeof (Elf64_Shdr
);
624 ehdr
.e_ident
[EI_CLASS
] = ELFCLASS32
;
625 ehdr
.e_type
= ELFCLASS32
;
626 ehdr
.e_ehsize
= sizeof (Elf32_Ehdr
);
627 ehdr
.e_phentsize
= sizeof (Elf32_Phdr
);
628 ehdr
.e_shentsize
= sizeof (Elf32_Shdr
);
633 ehdr
.e_machine
= EM_SPARCV9
;
635 ehdr
.e_machine
= EM_SPARC
;
637 #elif defined(__amd64)
638 ehdr
.e_machine
= EM_AMD64
;
640 ehdr
.e_machine
= EM_386
;
643 ehdr
.e_version
= EV_CURRENT
;
644 ehdr
.e_type
= ET_SUNWPSEUDO
;
646 ehdr
.e_shoff
= SECTION_OFFSET(0);
648 for (i
= 0; i
< NSECTIONS
; i
++) {
649 if (strcmp(data_sections
[i
].sect_name
,
651 ehdr
.e_shstrndx
= transidx
[i
];
653 if (sect_valid(&data_sections
[i
], mp
))
657 if ((error
= uiomove((char *)&ehdr
+ uio
->uio_loffset
,
658 sizeof (ehdr
) - uio
->uio_loffset
, UIO_READ
, uio
)) != 0 ||
664 * Go through and construct section headers for each section.
667 for (i
= 0; i
< NSECTIONS
; i
++) {
668 sp
= &data_sections
[i
];
670 if (!sect_valid(sp
, mp
))
673 if (uio
->uio_loffset
< SECTION_OFFSET(j
+1)) {
674 shdr
.sh_link
= transidx
[sp
->sect_link
];
675 shdr
.sh_entsize
= sp
->sect_entsize
;
677 shdr
.sh_name
= sp
->sect_str
;
678 shdr
.sh_type
= sp
->sect_type
;
679 shdr
.sh_flags
= sp
->sect_flags
;
680 shdr
.sh_addr
= sect_addr(sp
, mp
);
681 shdr
.sh_offset
= data_offset(sp
, mp
);
682 shdr
.sh_size
= sect_size(sp
, mp
);
683 shdr
.sh_addralign
= sp
->sect_align
;
685 off
= uio
->uio_loffset
- SECTION_OFFSET(j
);
686 if ((error
= uiomove((char *)&shdr
+ off
,
687 sizeof (shdr
) - off
, UIO_READ
, uio
)) != 0 ||
696 * Output the data for each section
698 for (i
= 0; i
< NSECTIONS
; i
++) {
700 sp
= &data_sections
[i
];
701 nextoff
= next_offset(i
, mp
);
702 if (sect_valid(sp
, mp
) && sp
->sect_type
!= SHT_NOBITS
&&
703 uio
->uio_loffset
< nextoff
) {
705 if (sp
->sect_id
== SECT_TYPE_INFO
)
706 addr
= &dnode
->objfs_data_info
;
708 addr
= (void *)sect_addr(sp
, mp
);
709 off
= uio
->uio_loffset
- data_offset(sp
, mp
);
712 * The symtab requires special processing to convert
713 * the st_shndx field to SHN_ABS. Otherwise, simply
714 * copy the data in bulk.
716 if (sp
->sect_id
== SECT_TYPE_SYMTAB
)
717 error
= read_symtab(addr
, sect_size(sp
, mp
),
720 error
= uiomove((char *)addr
+ off
,
721 sect_size(sp
, mp
) - off
, UIO_READ
, uio
);
723 if (error
!= 0 || uio
->uio_resid
<= 0)
727 * If the next section needs to be aligned, pad out with
730 if (uio
->uio_loffset
< nextoff
) {
731 uint64_t padding
= 0;
733 ASSERT(nextoff
- uio
->uio_loffset
<
736 if ((error
= uiomove(&padding
,
737 nextoff
- uio
->uio_loffset
, UIO_READ
,
738 uio
)) != 0 || uio
->uio_resid
<= 0)
746 objfs_data_unlock(vp
);
753 objfs_data_seek(vnode_t
*vp
, offset_t off
, offset_t
*offp
,
754 caller_context_t
*ct
)
759 static const struct vnodeops objfs_ops_data
= {
760 .vnop_name
= "objfs data file",
761 .vop_open
= objfs_data_open
,
762 .vop_close
= objfs_common_close
,
763 .vop_ioctl
= fs_inval
,
764 .vop_getattr
= objfs_data_getattr
,
765 .vop_access
= objfs_data_access
,
766 .vop_inactive
= gfs_vop_inactive
,
767 .vop_read
= objfs_data_read
,
768 .vop_seek
= objfs_data_seek
,
769 .vop_map
= gfs_vop_map
,