nuttx/sched/module/mod_insmod.c
Xiang Xiao 4a16cf71f9 Fix -Werror=nonnull-compare and -Werror=format-truncation=
Error: module/mod_insmod.c:203:3: error: 'strncpy' specified bound 16 equals destination size [-Werror=stringop-truncation]
  203 |   strncpy(modp->modname, modname, MODLIB_NAMEMAX);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

wqueue/kwork_thread.c: In function 'work_start_lowpri':
Error: wqueue/kwork_thread.c:212:22: error: '%lx' directive output may be truncated writing between 1 and 16 bytes into a region of size 14 [-Werror=format-truncation=]
  212 |   snprintf(args, 16, "0x%" PRIxPTR, (uintptr_t)wqueue);

local/local_sockif.c: In function 'local_getsockname':
Error: local/local_sockif.c:392:11: error: 'strncpy' specified bound depends on the length of the source argument [-Werror=stringop-overflow=]
  392 |           strncpy(unaddr->sun_path, conn->lc_path, namelen);
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

chip/esp32_wifi_utils.c: In function 'esp_wifi_scan_event_parse':
Error: chip/esp32_wifi_utils.c:373:37: error: argument to 'sizeof' in 'memset' call is the same expression as the destination; did you mean to dereference it? [-Werror=sizeof-pointer-memaccess]
   memset(ap_list_buffer, 0x0, sizeof(ap_list_buffer));
                                     ^

stdio/lib_fputs.c: In function 'fputs':
Error: stdio/lib_fputs.c:99:9: error: nonnull argument 's' compared to NULL [-Werror=nonnull-compare]
   if (s == NULL || stream == NULL)
         ^
Error: stdio/lib_fputs.c:99:27: error: nonnull argument 'stream' compared to NULL [-Werror=nonnull-compare]
   if (s == NULL || stream == NULL)
                           ^

stdio/lib_vfprintf.c: In function 'vfprintf':
Error: stdio/lib_vfprintf.c:40:6: error: nonnull argument 'stream' compared to NULL [-Werror=nonnull-compare]
   if (stream)
      ^

string/lib_strdup.c: In function 'strdup':
Error: string/lib_strdup.c:39:6: error: nonnull argument 's' compared to NULL [-Werror=nonnull-compare]
   if (s)
      ^

string/lib_strndup.c: In function 'strndup':
Error: string/lib_strndup.c:56:6: error: nonnull argument 's' compared to NULL [-Werror=nonnull-compare]
   if (s)
      ^

string/lib_strpbrk.c: In function 'strpbrk':
Error: string/lib_strpbrk.c:39:7: error: nonnull argument 'str' compared to NULL [-Werror=nonnull-compare]
   if (!str || !charset)
       ^~~~
Error: string/lib_strpbrk.c:39:15: error: nonnull argument 'charset' compared to NULL [-Werror=nonnull-compare]
   if (!str || !charset)
               ^~~~~~~~

string/lib_strrchr.c: In function 'strrchr':
Error: string/lib_strrchr.c:40:6: error: nonnull argument 's' compared to NULL [-Werror=nonnull-compare]
   if (s)
      ^

Error: time/lib_asctimer.c:73:50: error: '%d' directive output may be truncated writing between 1 and 11 bytes into a region of size between 0 and 12 [-Werror=format-truncation=]
   snprintf(buf, 26, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
                                                  ^~
time/lib_asctimer.c:73:21: note: directive argument in the range [-2147481748, 2147483647]
   snprintf(buf, 26, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
time/lib_asctimer.c:73:3: note: 'snprintf' output between 17 and 68 bytes into a destination of size 26
   snprintf(buf, 26, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            g_wday_name[tp->tm_wday], g_mon_name[tp->tm_mon],
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            tp->tm_mday, tp->tm_hour, tp->tm_min, tp->tm_sec,
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            1900 + tp->tm_year);
            ~~~~~~~~~~~~~~~~~~~

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
2022-03-02 15:55:38 +08:00

273 lines
9.2 KiB
C

/****************************************************************************
* sched/module/mod_insmod.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 <sys/types.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/kmalloc.h>
#include <nuttx/module.h>
#include <nuttx/lib/modlib.h>
#ifdef CONFIG_MODULE
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef MIN
# define MIN(a,b) (a < b ? a : b)
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mod_dumploadinfo
****************************************************************************/
#ifdef CONFIG_DEBUG_BINFMT_INFO
static void mod_dumploadinfo(FAR struct mod_loadinfo_s *loadinfo)
{
int i;
binfo("LOAD_INFO:\n");
binfo(" textalloc: %08lx\n", (long)loadinfo->textalloc);
binfo(" datastart: %08lx\n", (long)loadinfo->datastart);
binfo(" textsize: %ld\n", (long)loadinfo->textsize);
binfo(" datasize: %ld\n", (long)loadinfo->datasize);
binfo(" textalign: %zu\n", loadinfo->textalign);
binfo(" dataalign: %zu\n", loadinfo->dataalign);
binfo(" filelen: %ld\n", (long)loadinfo->filelen);
binfo(" filfd: %d\n", loadinfo->filfd);
binfo(" symtabidx: %d\n", loadinfo->symtabidx);
binfo(" strtabidx: %d\n", loadinfo->strtabidx);
binfo("ELF Header:\n");
binfo(" e_ident: %02x %02x %02x %02x\n",
loadinfo->ehdr.e_ident[0], loadinfo->ehdr.e_ident[1],
loadinfo->ehdr.e_ident[2], loadinfo->ehdr.e_ident[3]);
binfo(" e_type: %04x\n", loadinfo->ehdr.e_type);
binfo(" e_machine: %04x\n", loadinfo->ehdr.e_machine);
binfo(" e_version: %08x\n", loadinfo->ehdr.e_version);
binfo(" e_entry: %08lx\n", (long)loadinfo->ehdr.e_entry);
binfo(" e_phoff: %ju\n", (uintmax_t)loadinfo->ehdr.e_phoff);
binfo(" e_shoff: %ju\n", (uintmax_t)loadinfo->ehdr.e_shoff);
binfo(" e_flags: %08x\n", loadinfo->ehdr.e_flags);
binfo(" e_ehsize: %d\n", loadinfo->ehdr.e_ehsize);
binfo(" e_phentsize: %d\n", loadinfo->ehdr.e_phentsize);
binfo(" e_phnum: %d\n", loadinfo->ehdr.e_phnum);
binfo(" e_shentsize: %d\n", loadinfo->ehdr.e_shentsize);
binfo(" e_shnum: %d\n", loadinfo->ehdr.e_shnum);
binfo(" e_shstrndx: %d\n", loadinfo->ehdr.e_shstrndx);
if (loadinfo->shdr && loadinfo->ehdr.e_shnum > 0)
{
for (i = 0; i < loadinfo->ehdr.e_shnum; i++)
{
FAR Elf_Shdr *shdr = &loadinfo->shdr[i];
binfo("Sections %d:\n", i);
binfo(" sh_name: %08x\n", shdr->sh_name);
binfo(" sh_type: %08x\n", shdr->sh_type);
binfo(" sh_flags: %08jx\n", (uintmax_t)shdr->sh_flags);
binfo(" sh_addr: %08jx\n", (uintmax_t)shdr->sh_addr);
binfo(" sh_offset: %ju\n", (uintmax_t)shdr->sh_offset);
binfo(" sh_size: %ju\n", (uintmax_t)shdr->sh_size);
binfo(" sh_link: %d\n", shdr->sh_link);
binfo(" sh_info: %d\n", shdr->sh_info);
binfo(" sh_addralign: %ju\n", (uintmax_t)shdr->sh_addralign);
binfo(" sh_entsize: %ju\n", (uintmax_t)shdr->sh_entsize);
}
}
}
#else
# define mod_dumploadinfo(i)
#endif
/****************************************************************************
* Name: mod_dumpinitializer
****************************************************************************/
#ifdef CONFIG_MODLIB_DUMPBUFFER
static void mod_dumpinitializer(mod_initializer_t initializer,
FAR struct mod_loadinfo_s *loadinfo)
{
modlib_dumpbuffer("Initializer code", (FAR const uint8_t *)initializer,
MIN(loadinfo->textsize - loadinfo->ehdr.e_entry, 512));
}
#else
# define mod_dumpinitializer(b,l)
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: insmod
*
* Description:
* Verify that the file is an ELF module binary and, if so, load the
* module into kernel memory and initialize it for use.
*
* NOTE: modlib_setsymtab() had to have been called in board-specific OS
* logic prior to calling this function from application logic (perhaps via
* boardctl(BOARDIOC_OS_SYMTAB). Otherwise, insmod will be unable to
* resolve symbols in the OS module.
*
* Input Parameters:
*
* filename - Full path to the module binary to be loaded
* modname - The name that can be used to refer to the module after
* it has been loaded.
*
* Returned Value:
* A non-NULL module handle that can be used on subsequent calls to other
* module interfaces is returned on success. If insmod() was unable to
* load the module insmod() will return a NULL handle and the errno
* variable will be set appropriately.
*
****************************************************************************/
FAR void *insmod(FAR const char *filename, FAR const char *modname)
{
struct mod_loadinfo_s loadinfo;
FAR struct module_s *modp;
mod_initializer_t initializer;
int ret;
DEBUGASSERT(filename != NULL && modname != NULL);
binfo("Loading file: %s\n", filename);
/* Get exclusive access to the module registry */
modlib_registry_lock();
/* Check if this module is already installed */
if (modlib_registry_find(modname) != NULL)
{
ret = -EEXIST;
goto errout_with_lock;
}
/* Initialize the ELF library to load the program binary. */
ret = modlib_initialize(filename, &loadinfo);
mod_dumploadinfo(&loadinfo);
if (ret != 0)
{
berr("ERROR: Failed to initialize to load module: %d\n", ret);
goto errout_with_loadinfo;
}
/* Allocate a module registry entry to hold the module data */
modp = (FAR struct module_s *)kmm_zalloc(sizeof(struct module_s));
if (ret != 0)
{
binfo("Failed to initialize for load of ELF program: %d\n", ret);
goto errout_with_loadinfo;
}
/* Save the module name in the registry entry */
strlcpy(modp->modname, modname, MODLIB_NAMEMAX);
/* Load the program binary */
ret = modlib_load(&loadinfo);
mod_dumploadinfo(&loadinfo);
if (ret != 0)
{
binfo("Failed to load ELF program binary: %d\n", ret);
goto errout_with_registry_entry;
}
/* Bind the program to the kernel symbol table */
ret = modlib_bind(modp, &loadinfo);
if (ret != 0)
{
binfo("Failed to bind symbols program binary: %d\n", ret);
goto errout_with_load;
}
/* Save the load information */
modp->textalloc = (FAR void *)loadinfo.textalloc;
modp->dataalloc = (FAR void *)loadinfo.datastart;
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
modp->textsize = loadinfo.textsize;
modp->datasize = loadinfo.datasize;
#endif
/* Get the module initializer entry point */
initializer = (mod_initializer_t)(loadinfo.textalloc +
loadinfo.ehdr.e_entry);
#if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_MODULE)
modp->initializer = initializer;
#endif
mod_dumpinitializer(initializer, &loadinfo);
/* Call the module initializer */
ret = initializer(&modp->modinfo);
if (ret < 0)
{
binfo("Failed to initialize the module: %d\n", ret);
goto errout_with_load;
}
/* Add the new module entry to the registry */
modlib_registry_add(modp);
modlib_uninitialize(&loadinfo);
modlib_registry_unlock();
return (FAR void *)modp;
errout_with_load:
modlib_unload(&loadinfo);
modlib_undepend(modp);
errout_with_registry_entry:
kmm_free(modp);
errout_with_loadinfo:
modlib_uninitialize(&loadinfo);
errout_with_lock:
modlib_registry_unlock();
set_errno(-ret);
return NULL;
}
#endif /* CONFIG_MODULE */