Print this page
file: support DT_SUNW_KMOD usefully

@@ -77,10 +77,11 @@
 #include <procfs.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/elf.h>
+#include <sys/link.h>
 #include <elfcap.h>
 #include "file.h"
 #include "elf_read.h"
 
 extern const char *File;

@@ -139,11 +140,11 @@
         format = get_format();
 
         /* will convert only these types */
         if (type != ELF_T_EHDR && type != ELF_T_PHDR &&
             type != ELF_T_SHDR && type != ELF_T_WORD &&
-            type != ELF_T_CAP)
+            type != ELF_T_CAP && type != ELF_T_DYN)
                 return (ELF_READ_FAIL);
 
         src.d_buf = (Elf_Void *)hdr;
         src.d_type = type;
         src.d_version = version;

@@ -413,21 +414,16 @@
  *                      in Elf_Info with corresponding flags.
  */
 static int
 process_shdr(Elf_Info *EI)
 {
-        int             capn, mac;
+        int             mac;
         int             i, j, idx;
-        FILE_ELF_OFF_T  cap_off;
-        FILE_ELF_SIZE_T csize;
         char            *strtab;
         size_t          strtab_sz;
-        Elf_Cap         Chdr;
         Elf_Shdr        *shdr = &EI_Shdr;
 
-
-        csize = sizeof (Elf_Cap);
         mac = EI_Ehdr.e_machine;
 
         /* if there are no sections, return success anyway */
         if (EI_Ehdr.e_shoff == 0 && EI_Ehdr_shnum == 0)
                 return (ELF_READ_OKAY);

@@ -455,13 +451,19 @@
                 if (shdr->sh_type == SHT_NULL) {
                         idx--;
                         continue;
                 }
 
-                cap_off = shdr->sh_offset;
                 if (shdr->sh_type == SHT_SUNW_cap) {
                         char capstr[128];
+                        Elf_Cap         Chdr;
+                        FILE_ELF_OFF_T  cap_off;
+                        FILE_ELF_SIZE_T csize;
+                        int capn;
+
+                        cap_off = shdr->sh_offset;
+                        csize = sizeof (Elf_Cap);
 
                         if (shdr->sh_size == 0 || shdr->sh_entsize == 0) {
                                 (void) fprintf(stderr, ELF_ERR_ELFCAP1,
                                     File, EI->file);
                                 return (ELF_READ_FAIL);

@@ -469,12 +471,12 @@
                         capn = (shdr->sh_size / shdr->sh_entsize);
                         for (j = 0; j < capn; j++) {
                                 /*
                                  * read cap and xlate the values
                                  */
-                                if (pread64(EI->elffd, &Chdr, csize, cap_off)
-                                    != csize ||
+                                if ((pread64(EI->elffd, &Chdr, csize, cap_off)
+                                    != csize) ||
                                     file_xlatetom(ELF_T_CAP, (char *)&Chdr)
                                     == 0) {
                                         (void) fprintf(stderr, ELF_ERR_ELFCAP2,
                                             File, EI->file);
                                         return (ELF_READ_FAIL);

@@ -501,10 +503,43 @@
                                             sizeof (EI->cap_str));
 
                                 (void) strlcat(EI->cap_str, capstr,
                                     sizeof (EI->cap_str));
                         }
+                } else if (shdr->sh_type == SHT_DYNAMIC) {
+                        Elf_Dyn dyn;
+                        FILE_ELF_SIZE_T dsize;
+                        FILE_ELF_OFF_T doff;
+                        int dynn;
+
+                        doff = shdr->sh_offset;
+                        dsize = sizeof (Elf_Dyn);
+
+                        if (shdr->sh_size == 0 || shdr->sh_entsize == 0) {
+                                (void) fprintf(stderr, ELF_ERR_DYNAMIC1,
+                                    File, EI->file);
+                                return (ELF_READ_FAIL);
+                        }
+
+                        dynn = (shdr->sh_size / shdr->sh_entsize);
+                        for (j = 0; j < dynn; j++) {
+                                if (pread64(EI->elffd, &dyn, dsize, doff)
+                                    != dsize ||
+                                    file_xlatetom(ELF_T_DYN, (char *)&dyn)
+                                    == 0) {
+                                        (void) fprintf(stderr, ELF_ERR_DYNAMIC2,
+                                            File, EI->file);
+                                        return (ELF_READ_FAIL);
+                                }
+
+                                doff += dsize;
+
+                                if ((dyn.d_tag == DT_SUNW_KMOD) &&
+                                    (dyn.d_un.d_val == 1)) {
+                                        EI->kmod = B_TRUE;
+                                }
+                        }
                 }
 
                 /*
                  * Definition time:
                  *      - "not stripped" means that an executable file