This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new 133430658 coredump:support coredump command restore coredump form 
block device
133430658 is described below

commit 1334306585f66534a3f16a9ba99f63bd69bf03b3
Author: anjiahao <[email protected]>
AuthorDate: Thu Nov 9 12:08:11 2023 +0800

    coredump:support coredump command restore coredump form block device
    
    Signed-off-by: anjiahao <[email protected]>
---
 system/coredump/coredump.c | 370 +++++++++++++++++++++++++++++++++++++++------
 1 file changed, 322 insertions(+), 48 deletions(-)

diff --git a/system/coredump/coredump.c b/system/coredump/coredump.c
index a29ffc96b..2dfc61f5a 100644
--- a/system/coredump/coredump.c
+++ b/system/coredump/coredump.c
@@ -23,68 +23,246 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
-#include <nuttx/streams.h>
-#include <nuttx/binfmt/binfmt.h>
-
 #include <sys/types.h>
-
-#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <stdlib.h>
 #include <syslog.h>
+#include <dirent.h>
+#include <elf.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
 
-#include <execinfo.h>
+#include <nuttx/binfmt/binfmt.h>
+#include <nuttx/streams.h>
 
 /****************************************************************************
- * Public Functions
+ * Private Types
  ****************************************************************************/
 
+typedef CODE void (*dumpfile_cb_t)(FAR char *path, FAR const char *filename,
+                                   FAR void *arg);
+
 /****************************************************************************
- * coredump_main
+ * Private Functions
  ****************************************************************************/
 
-int main(int argc, FAR char *argv[])
+/****************************************************************************
+ * dumpfile_iterate
+ ****************************************************************************/
+
+#ifdef CONFIG_BOARD_COREDUMP_BLKDEV
+static int dumpfile_iterate(FAR char *path, dumpfile_cb_t cb, FAR void *arg)
 {
-  FAR struct lib_stdoutstream_s *outstream;
-  FAR struct lib_hexdumpstream_s *hstream;
-  FAR struct lib_lzfoutstream_s *lstream;
-  char *name = NULL;
-  FAR void *stream;
-  int logmask;
-  int pid = 0;
-  FILE *file;
+  FAR struct dirent *entry;
+  FAR DIR *dir;
+  int ret;
+
+  dir = opendir(path);
+  if (dir == NULL)
+    {
+      ret = mkdir(path, 0777);
+      if (ret < 0)
+        {
+          return ret;
+        }
+    }
+
+  while ((entry = readdir(dir)) != NULL)
+    {
+      if (entry->d_type == DT_REG && !strncmp(entry->d_name, "core-", 5))
+        {
+          cb(path, entry->d_name, arg);
+        }
+    }
+
+  closedir(dir);
+  return 0;
+}
+
+/****************************************************************************
+ * dumpfile_count
+ ****************************************************************************/
+
+static void dumpfile_count(FAR char *path, FAR const char *filename,
+                           FAR void *arg)
+{
+  FAR size_t *max = (FAR size_t *)arg;
+
+  *max += 1;
+}
+
+/****************************************************************************
+ * dumpfile_delete
+ ****************************************************************************/
+
+static void dumpfile_delete(FAR char *path, FAR const char *filename,
+                            FAR void *arg)
+{
+  FAR char *dumppath = arg;
+
+  sprintf(dumppath, "%s/%s", path, filename);
+  printf("Remove %s\n", dumppath);
+  remove(dumppath);
+}
+
+/****************************************************************************
+ * coredump_restore
+ ****************************************************************************/
+
+static void coredump_restore(FAR char *savepath, size_t maxfile)
+{
+  FAR struct coredump_info_s *info;
+  unsigned char *swap;
+  char dumppath[PATH_MAX];
+  struct geometry geo;
+  ssize_t writesize;
+  ssize_t readsize;
+  struct tm *dtime;
+  size_t offset = 0;
+  size_t max = 0;
+  int dumpfd;
+  int blkfd;
+  int ret;
+
+  blkfd = open(CONFIG_BOARD_COREDUMP_BLKDEV_PATH, O_RDWR);
+  if (blkfd < 0)
+    {
+      return;
+    }
+
+  ret = ioctl(blkfd, BIOC_GEOMETRY, (unsigned long)((uintptr_t)&geo));
+  if (ret < 0)
+    {
+      goto blkfd_err;
+    }
+
+  info = malloc(geo.geo_sectorsize);
+  if (info == NULL)
+    {
+      goto blkfd_err;
+    }
 
-  if (argc >= 2)
+  lseek(blkfd, (geo.geo_nsectors - 1) * geo.geo_sectorsize, SEEK_SET);
+  read(blkfd, info, geo.geo_sectorsize);
+  if (info->magic != COREDUMP_MAGIC)
     {
-      pid = atoi(argv[1]);
-      if (pid == 0)
+      printf("%s coredump not found!\n", CONFIG_BOARD_COREDUMP_BLKDEV_PATH);
+      goto info_err;
+    }
+
+  ret = dumpfile_iterate(savepath, dumpfile_count, &max);
+  if (ret < 0)
+    {
+      goto info_err;
+    }
+
+  if (max >= maxfile)
+    {
+      ret = dumpfile_iterate(savepath, dumpfile_delete, dumppath);
+      if (ret < 0)
         {
-          name = argv[1];
+          goto info_err;
         }
+    }
+
+  ret = snprintf(dumppath, sizeof(dumppath),
+                 "%s/core-%s", savepath,
+                 info->name.version);
+  dtime = localtime(&info->time);
+  if (dtime)
+    {
+      ret += snprintf(dumppath + ret, sizeof(dumppath) - ret,
+                      "-%d-%d-%d-%d-%d", dtime->tm_mon + 1,
+                      dtime->tm_mday, dtime->tm_hour,
+                      dtime->tm_min, dtime->tm_sec);
+    }
 
-      if (argc >= 3)
+#ifdef CONFIG_BOARD_COREDUMP_COMPRESSION
+  ret += snprintf(dumppath + ret, sizeof(dumppath) - ret, ".lzf");
+#else
+  ret += snprintf(dumppath + ret, sizeof(dumppath) - ret, ".core");
+#endif
+
+  while (ret--)
+    {
+      if (dumppath[ret] == ' ' || dumppath[ret] == ':')
         {
-          if (name == NULL)
-            {
-              name = argv[2];
-            }
-          else
-            {
-              pid = atoi(argv[2]);
-            }
+          dumppath[ret] = '-';
         }
     }
 
-  if (pid == 0)
+  dumpfd = open(dumppath, O_CREAT | O_WRONLY | O_TRUNC, 0777);
+  if (dumpfd < 0)
+    {
+      printf("Open %s fail\n", dumppath);
+      goto info_err;
+    }
+
+  swap = malloc(geo.geo_sectorsize);
+  if (swap == NULL)
+    {
+      printf("Malloc fail\n");
+      goto fd_err;
+    }
+
+  lseek(blkfd, 0, SEEK_SET);
+  while (offset < info->size)
     {
-      pid = INVALID_PROCESS_ID;
+      readsize = read(blkfd, swap, geo.geo_sectorsize);
+      if (readsize < 0)
+        {
+          printf("Read %s fail\n", CONFIG_BOARD_COREDUMP_BLKDEV_PATH);
+          break;
+        }
+
+      writesize = write(dumpfd, swap, readsize);
+      if (writesize != readsize)
+        {
+          printf("Write %s fail\n", dumppath);
+          break;
+        }
+
+      offset += writesize;
     }
 
-  if (name != NULL)
+  printf("Coredump finish [%s][%zu]\n", dumppath, info->size);
+  info->magic = 0;
+  lseek(blkfd, (geo.geo_nsectors - 1) * geo.geo_sectorsize, SEEK_SET);
+  write(blkfd, info, geo.geo_sectorsize);
+  free(swap);
+fd_err:
+  close(dumpfd);
+info_err:
+  free(info);
+blkfd_err:
+  close(blkfd);
+}
+
+#endif
+
+/****************************************************************************
+ * coredump_now
+ ****************************************************************************/
+
+static int coredump_now(int pid, FAR char *filename)
+{
+  FAR struct lib_stdoutstream_s *outstream;
+  FAR struct lib_hexdumpstream_s *hstream;
+#ifdef CONFIG_BOARD_COREDUMP_COMPRESSION
+  FAR struct lib_lzfoutstream_s *lstream;
+#endif
+  FAR void *stream;
+  FAR FILE *file;
+  int logmask;
+
+  if (filename != NULL)
     {
-      file = fopen(name, "w");
+      file = fopen(filename, "w");
       if (file == NULL)
         {
-          return 1;
+          return -errno;
         }
     }
   else
@@ -92,29 +270,37 @@ int main(int argc, FAR char *argv[])
       file = stdout;
     }
 
-  hstream = malloc(sizeof(*hstream) + sizeof(*lstream) + sizeof(*outstream));
+#ifdef CONFIG_BOARD_COREDUMP_COMPRESSION
+  hstream = malloc(sizeof(*hstream) + sizeof(*lstream) +
+                   sizeof(*outstream));
+#else
+  hstream = malloc(sizeof(*hstream) + sizeof(*outstream));
+#endif
+
   if (hstream == NULL)
     {
-      if (name != NULL)
+      if (filename != NULL)
         {
           fclose(file);
         }
 
-      return 1;
+      return -ENOMEM;
     }
 
+#ifdef CONFIG_BOARD_COREDUMP_COMPRESSION
   lstream = (FAR void *)(hstream + 1);
   outstream = (FAR void *)(lstream + 1);
-
-  logmask = setlogmask(LOG_ALERT);
+#else
+  outstream = (FAR void *)(hstream + 1);
+#endif
 
   printf("Start coredump:\n");
+  logmask = setlogmask(LOG_ALERT);
 
   /* Initialize hex output stream */
 
   lib_stdoutstream(outstream, file);
   lib_hexdumpstream(hstream, (FAR void *)outstream);
-
   stream = hstream;
 
 #ifdef CONFIG_BOARD_COREDUMP_COMPRESSION
@@ -129,20 +315,108 @@ int main(int argc, FAR char *argv[])
   /* Do core dump */
 
   core_dump(NULL, stream, pid);
-
-#ifdef CONFIG_BOARD_COREDUMP_COMPRESSION
+  setlogmask(logmask);
+#  ifdef CONFIG_BOARD_COREDUMP_COMPRESSION
   printf("Finish coredump (Compression Enabled).\n");
-#else
+#  else
   printf("Finish coredump.\n");
+#  endif
+
+  free(hstream);
+  if (filename != NULL)
+    {
+      fclose(file);
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * usage
+ ****************************************************************************/
+
+static void usage(FAR const char *progname, int exitcode)
+{
+  fprintf(stderr, "%s [option]:\n", progname);
+  fprintf(stderr, "Default usage, will coredump directly\n");
+  fprintf(stderr, "\t -p, --pid <pid>, Default, all thread\n");
+  fprintf(stderr, "\t -f, --filename <filename>, Default stdout\n");
+
+#ifdef CONFIG_BOARD_COREDUMP_BLKDEV
+  fprintf(stderr, "Second usage, will restore coredump"
+                  "from %s to savepath\n",
+                   CONFIG_BOARD_COREDUMP_BLKDEV_PATH);
+  fprintf(stderr, "\t -s, --savepath <savepath>\n");
+  fprintf(stderr, "\t -m, --maxfile <maxfile>,"
+                  "Maximum number of coredump files, Default 1\n");
 #endif
+  exit(exitcode);
+}
 
-  setlogmask(logmask);
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
 
-  free(hstream);
+/****************************************************************************
+ * coredump_main
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+#ifdef CONFIG_BOARD_COREDUMP_BLKDEV
+  FAR char *savepath = NULL;
+  size_t maxfile = 1;
+#endif
+  char *name = NULL;
+  int pid = INVALID_PROCESS_ID;
+  int ret;
 
-  if (name != NULL)
+  struct option options[] =
     {
-      fclose(file);
+      {"pid", 1, NULL, 'p'},
+      {"filename", 1, NULL, 'f'},
+#ifdef CONFIG_BOARD_COREDUMP_BLKDEV
+      {"savepath", 1, NULL, 's'},
+      {"maxfile", 1, NULL, 'm'},
+#endif
+      {"help", 0, NULL, 'h'}
+    };
+
+  while ((ret = getopt_long(argc, argv, "p:f:s:m:h", options, NULL))
+         != ERROR)
+    {
+      switch (ret)
+        {
+          case 'p':
+            pid = atoi(optarg);
+            break;
+          case 'f':
+            name = optarg;
+            break;
+#ifdef CONFIG_BOARD_COREDUMP_BLKDEV
+          case 's':
+            savepath = optarg;
+            break;
+          case 'm':
+            maxfile = atoi(optarg);
+            break;
+#endif
+          case 'h':
+          default:
+            usage(argv[0], EXIT_SUCCESS);
+            break;
+        }
+    }
+
+#ifdef CONFIG_BOARD_COREDUMP_BLKDEV
+  if (savepath != NULL)
+    {
+      coredump_restore(savepath, maxfile);
+    }
+  else
+#endif
+    {
+      coredump_now(pid, name);
     }
 
   return 0;

Reply via email to