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;