212 lines
5.9 KiB
C
212 lines
5.9 KiB
C
/****************************************************************************
|
|
* libs/libc/modlib/modlib_sections.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <debug.h>
|
|
|
|
#include "libc.h"
|
|
#include "modlib/modlib.h"
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: modlib_sectname
|
|
*
|
|
* Description:
|
|
* Get the symbol name in loadinfo->iobuffer[].
|
|
*
|
|
* Returned Value:
|
|
* 0 (OK) is returned on success and a negated errno is returned on
|
|
* failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static inline int modlib_sectname(FAR struct mod_loadinfo_s *loadinfo,
|
|
FAR const Elf_Shdr *shdr)
|
|
{
|
|
FAR Elf_Shdr *shstr;
|
|
off_t offset;
|
|
size_t bytesread = 0;
|
|
int shstrndx;
|
|
int ret;
|
|
|
|
/* Get the section header table index of the entry associated with the
|
|
* section name string table. If the file has no section name string table,
|
|
* this member holds the value SH_UNDEF.
|
|
*/
|
|
|
|
shstrndx = loadinfo->ehdr.e_shstrndx;
|
|
if (shstrndx == SHN_UNDEF)
|
|
{
|
|
berr("ERROR: No section header string table\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* Allocate an I/O buffer. This buffer is used by modlib_sectname() to
|
|
* accumulate the variable length symbol name.
|
|
*/
|
|
|
|
ret = modlib_allocbuffer(loadinfo);
|
|
if (ret < 0)
|
|
{
|
|
berr("ERROR: modlib_allocbuffer failed: %d\n", ret);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
/* Get the section name string table section header */
|
|
|
|
shstr = &loadinfo->shdr[shstrndx];
|
|
|
|
/* Get the file offset to the string that is the name of the section. This
|
|
* is the sum of:
|
|
*
|
|
* shstr->sh_offset: The file offset to the first byte of the section
|
|
* header string table data.
|
|
* shdr->sh_name: The offset to the name of the section in the section
|
|
* name table
|
|
*/
|
|
|
|
offset = shstr->sh_offset + shdr->sh_name;
|
|
|
|
/* Loop until we get the entire section name into memory */
|
|
|
|
for (; ; )
|
|
{
|
|
FAR uint8_t *buffer = &loadinfo->iobuffer[bytesread];
|
|
size_t readlen = loadinfo->buflen - bytesread;
|
|
|
|
/* Get the number of bytes to read */
|
|
|
|
if (offset + readlen > loadinfo->filelen)
|
|
{
|
|
if (loadinfo->filelen <= offset)
|
|
{
|
|
berr("ERROR: At end of file\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
readlen = loadinfo->filelen - offset;
|
|
}
|
|
|
|
/* Read that number of bytes into the array */
|
|
|
|
ret = modlib_read(loadinfo, buffer, readlen, offset);
|
|
if (ret < 0)
|
|
{
|
|
berr("ERROR: Failed to read section name: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
bytesread += readlen;
|
|
|
|
/* Did we read the NUL terminator? */
|
|
|
|
if (memchr(buffer, '\0', readlen) != NULL)
|
|
{
|
|
/* Yes, the buffer contains a NUL terminator. */
|
|
|
|
return OK;
|
|
}
|
|
|
|
/* No.. then we have to read more */
|
|
|
|
ret = modlib_reallocbuffer(loadinfo, CONFIG_MODLIB_BUFFERINCR);
|
|
if (ret < 0)
|
|
{
|
|
berr("ERROR: mod_reallocbuffer failed: %d\n", ret);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/* We will not get here */
|
|
|
|
return OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: modlib_findsection
|
|
*
|
|
* Description:
|
|
* A section by its name.
|
|
*
|
|
* Input Parameters:
|
|
* loadinfo - Load state information
|
|
* sectname - Name of the section to find
|
|
*
|
|
* Returned Value:
|
|
* On success, the index to the section is returned; A negated errno value
|
|
* is returned on failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int modlib_findsection(FAR struct mod_loadinfo_s *loadinfo,
|
|
FAR const char *sectname)
|
|
{
|
|
int i;
|
|
|
|
/* Search through the shdr[] array in loadinfo for a section named
|
|
* 'sectname'
|
|
*/
|
|
|
|
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
|
|
{
|
|
FAR const Elf_Shdr *shdr = &loadinfo->shdr[i];
|
|
|
|
/* Get the name of this section */
|
|
|
|
int ret = modlib_sectname(loadinfo, shdr);
|
|
if (ret < 0)
|
|
{
|
|
berr("ERROR: modlib_sectname failed: %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
/* Check if the name of this section is 'sectname' */
|
|
|
|
binfo("%d. Comparing \"%s\" and .\"%s\"\n",
|
|
i, loadinfo->iobuffer, sectname);
|
|
|
|
if (strcmp((FAR const char *)loadinfo->iobuffer, sectname) == 0)
|
|
{
|
|
/* We found it... return the index */
|
|
|
|
return i;
|
|
}
|
|
}
|
|
|
|
/* We failed to find a section with this name. */
|
|
|
|
return -ENOENT;
|
|
}
|