nealef commented on code in PR #7202:
URL: https://github.com/apache/incubator-nuttx/pull/7202#discussion_r981864061


##########
libs/libc/modlib/modlib_bind.c:
##########
@@ -518,6 +518,228 @@ static int modlib_relocateadd(FAR struct module_s *modp,
   return ret;
 }
 
+/****************************************************************************
+ * Name: modlib_relocatedyn
+ *
+ * Description:
+ *   Perform all relocations associated with a dynamic section.
+ *
+ * Returned Value:
+ *   0 (OK) is returned on success and a negated errno is returned on
+ *   failure.
+ *
+ ****************************************************************************/
+
+static int modlib_relocatedyn(FAR struct module_s *modp,
+                              FAR struct mod_loadinfo_s *loadinfo, int relidx)
+
+{
+  FAR Elf32_Shdr *shdr = &loadinfo->shdr[relidx];
+  FAR Elf32_Shdr *symhdr;
+  FAR Elf32_Dyn  *dyn = NULL;
+  FAR Elf32_Rel  *rels = NULL;
+  FAR Elf32_Rel  *rel;
+  FAR Elf32_Sym  *sym = NULL;
+  uintptr_t       addr;
+  int             ret;
+  int             i, iRel, iSym;
+  struct {
+       int     strOff;         /* Offset to string table */
+       int     symOff;         /* Offset to symbol table */
+       int     lSymTab;        /* Size of symbol table */
+       int     relEntSz;       /* Size of relocation entry */
+       int     relOff[2];      /* Offset to the relocation section */
+       int     relSz[2];       /* Size of relocation table */
+#define I_REL  0
+#define I_PLT  1
+#define N_RELS 2
+  } relData;
+
+  dyn = lib_malloc(shdr->sh_size);
+  ret = modlib_read(loadinfo, (FAR uint8_t *) dyn, shdr->sh_size, 
shdr->sh_offset);
+  if (ret < 0) 
+    {
+      berr("Failed to read dynamic section header");
+      return ret;
+    }
+
+  rels = lib_malloc(CONFIG_MODLIB_RELOCATION_BUFFERCOUNT * sizeof(Elf32_Rel));
+  if (!rels)
+    {
+      berr("Failed to allocate memory for elf relocation rels\n");
+      lib_free(dyn);
+      return -ENOMEM;
+    }
+
+  memset((void *) &relData, 0, sizeof(relData));
+
+  for (i = 0; dyn[i].d_tag != DT_NULL; i++) 
+    {
+      switch(dyn[i].d_tag) 
+       {
+          case DT_REL :
+              relData.relOff[I_REL] = dyn[i].d_un.d_val;
+              break;
+          case DT_RELSZ :
+              relData.relSz[I_REL] = dyn[i].d_un.d_val;
+              break;
+          case DT_RELENT :
+              relData.relEntSz = dyn[i].d_un.d_val;
+              break;
+         case DT_SYMTAB :
+             relData.symOff = dyn[i].d_un.d_val;
+             break;
+         case DT_STRTAB :
+             relData.strOff = dyn[i].d_un.d_val;
+             break;
+         case DT_JMPREL :
+             relData.relOff[I_PLT] = dyn[i].d_un.d_val;
+             break;
+         case DT_PLTRELSZ :
+             relData.relSz[I_PLT] = dyn[i].d_un.d_val;
+             break;
+        }
+    }
+
+  symhdr = &loadinfo->shdr[loadinfo->dsymtabidx];
+  sym = lib_malloc(symhdr->sh_size);
+  if (!sym)
+    {
+      berr("Error obtaining storage for dynamic symbol table");
+      lib_free(rels);
+      lib_free(dyn);
+      return -ENOMEM;
+    }
+
+  ret = modlib_read(loadinfo, (uint8_t *) sym, symhdr->sh_size, 
symhdr->sh_offset);
+  if (ret < 0) 
+    {
+      berr("Error reading dynamic symbol table - %d", ret);
+      lib_free(sym);
+      lib_free(rels);
+      lib_free(dyn);
+      return ret;
+    }
+
+  relData.lSymTab = relData.strOff - relData.symOff;
+
+  for (iRel = 0; iRel < N_RELS; iRel++)
+    {
+      if (relData.relOff[iRel] == 0)
+          continue;
+
+      /* Examine each relocation in the .rel.* section.
+       */
+
+      ret = OK;
+
+      for (i = 0; i < relData.relSz[iRel] / relData.relEntSz; i++)
+        {
+          /* Process each relocation entry */
+
+          rel = &rels[i % CONFIG_MODLIB_RELOCATION_BUFFERCOUNT];
+
+          if (!(i % CONFIG_MODLIB_RELOCATION_BUFFERCOUNT))
+            {
+              ret = modlib_read(loadinfo, (FAR uint8_t *) rels, 
+                                sizeof(Elf32_Rel) * 
CONFIG_MODLIB_RELOCATION_BUFFERCOUNT,
+                                relData.relOff[iRel] + i * sizeof(Elf32_Rel));
+              if (ret < 0)
+                {
+                  berr("ERROR: Section %d reloc %d: Failed to read relocation 
entry: %d\n",
+                       relidx, i, ret);
+                  break;
+                }
+            }
+
+          /* Calculate the relocation address. */
+
+          if (rel->r_offset < 0)
+            {
+              berr("ERROR: Section %d reloc %d: Relocation address out of 
range, offset %d\n",
+                   relidx, i, rel->r_offset);
+              ret = -EINVAL;
+              lib_free(sym);
+              lib_free(rels);
+              lib_free(dyn);
+              return ret;
+            }
+
+          /* Now perform the architecture-specific relocation */
+
+          if ((iSym = ELF32_R_SYM(rel->r_info)) != 0) 
+            {
+              if (sym[iSym].st_shndx == SHN_UNDEF)     /* We have an external 
reference */
+                {
+                    void *ep;
+
+                    ep = modlib_findglobal(modp, loadinfo, symhdr, &sym[iSym]);
+                    if (ep == NULL) 
+                      {
+                        berr("ERROR: Unable to resolve address of external 
reference %s\n",
+                             loadinfo->iobuffer);
+                        ret = -EINVAL;
+                        lib_free(sym);
+                        lib_free(rels);
+                        lib_free(dyn);
+                        return ret;
+                      }
+
+                    addr = rel->r_offset + loadinfo->textalloc;
+                   *(uintptr_t *)addr = (uintptr_t)ep;
+                }
+            }
+          else
+            {
+              Elf32_Sym dynSym;
+
+              addr = rel->r_offset - loadinfo->datasec + loadinfo->datastart;
+
+              if ((*(uint32_t *) addr) < loadinfo->datasec)
+                  dynSym.st_value = *(uint32_t *) addr + loadinfo->textalloc;
+              else
+                  dynSym.st_value = *(uint32_t *) addr - loadinfo->datasec + 
loadinfo->datastart;
+              ret = up_relocate(rel, &dynSym, addr);
+            }
+
+          if (ret < 0)
+            {
+              berr("ERROR: Section %d reloc %d: Relocation failed: %d\n", 
relidx, i, ret);
+              lib_free(sym);
+              lib_free(rels);
+              lib_free(dyn);
+              return ret;
+            }
+        }
+    }    
+
+  /* Iterate through the dynamic symbol table looking for global symbols to 
put in 
+   * our own symbol table for use with dlgetsym()
+   */
+
+  /* Relocate the entries in the table */
+  for (i = 0; i < (symhdr->sh_size / sizeof(Elf32_Sym)); i++)

Review Comment:
   Fixed



##########
libs/libc/modlib/modlib_load.c:
##########
@@ -148,75 +134,33 @@ static inline int modlib_loadfile(FAR struct 
mod_loadinfo_s *loadinfo)
   int ret;
   int i;
 
-  /* Read each section into memory that is marked SHF_ALLOC + SHT_NOBITS */
+  /* Read each PT_LOAD area into memory */
 
-  binfo("Loaded sections:\n");
+  binfo("Loading sections - text: %p.%x data: %p.%x\n",
+        
loadinfo->textalloc,loadinfo->textsize,loadinfo->datastart,loadinfo->datasize);
   text = (FAR uint8_t *)loadinfo->textalloc;
   data = (FAR uint8_t *)loadinfo->datastart;
 
-  for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
+  for (i = 0; i < loadinfo->ehdr.e_phnum; i++)
     {
-      FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
-
-      /* SHF_ALLOC indicates that the section requires memory during
-       * execution
-       */
-
-      if ((shdr->sh_flags & SHF_ALLOC) == 0)
-        {
-          continue;
-        }
-
-      /* SHF_WRITE indicates that the section address space is write-
-       * able
-       */
-
-      if ((shdr->sh_flags & SHF_WRITE) != 0)
-        {
-          pptr = &data;
-        }
-      else
-        {
-          pptr = &text;
-        }
-
-      *pptr = (FAR uint8_t *)_ALIGN_UP((uintptr_t)*pptr, shdr->sh_addralign);
+      FAR Elf32_Phdr *phdr = &loadinfo->phdr[i];
 
-      /* SHT_NOBITS indicates that there is no data in the file for the
-       * section.
-       */
-
-      if (shdr->sh_type != SHT_NOBITS)
+      if (phdr->p_type == PT_LOAD)
         {
-          /* Read the section data from sh_offset to the memory region */
-
-          ret = modlib_read(loadinfo, *pptr, shdr->sh_size, shdr->sh_offset);
+          if (phdr->p_flags & PF_X)
+              ret = modlib_read(loadinfo, text, phdr->p_filesz, 
phdr->p_offset);

Review Comment:
   Fixed



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to