On Mon, Sep 29, 2025 at 12:11 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
 Date: Mon, 29 Sep 2025 17:08:10 +1300
 From: Tao Liu <ltao(a)redhat.com>
 Subject: [Crash-utility] [PATCH v2 2/2] eppic.patch: Add customized
         functions to eppic
 To: devel(a)lists.crash-utility.osci.io
 Cc: jbrisson(a)linux.ibm.com
 Message-ID: <20250929040810.25718-3-ltao(a)redhat.com>
 Content-Type: text/plain; charset="US-ASCII"; x-default=true
 This patch will add the following functions to eppic:
 1) Allow main() as the entry for any eppic program. Previously only func()
    which companied by func_help() & func_usage() is regarded as the main
    entry of the eppic program. This constraint only makes sense for
 creating
    a crash-like cmd. If users only want to create a oneshot run program for
    fast testing, then the constraint is misleading. So this patch will add
    main() as entry for eppic programs.
 2) Add new command "eppic" for oneshot run eppic programs. Previously eppic
    expect programs to run as the form of crash-like cmd, and it is not
    convenient for oneshot run programs. With "eppic" command, people can
    use "edit -f" or any other editors to create eppic programs, then run
    it via "eppic myfile.c".
 3) Add a template for any new eppic program files. If "edit -f" a new
 file, a
    template with an example will be written into the new file. So users can
    refer to it when writting any eppic programs.
 Signed-off-by: Tao Liu <ltao(a)redhat.com>
 ---
  extensions/eppic.mk    |  13 ++-
  extensions/eppic.patch | 210 +++++++++++++++++++++++++++++++++++++++++
  2 files changed, 222 insertions(+), 1 deletion(-)
  create mode 100644 extensions/eppic.patch
 
I don't have much comment on this, only one thing:
For the eppic.patch, I would suggest using the same style with
gdb-16.2.patch. E.g:
...
--- gdb-16.2/gdb/c-typeprint.c.orig
+++ gdb-16.2/gdb/c-typeprint.c
@@ -1066,6 +1066,9 @@ c_type_print_base_struct_union (struct type *type,
struct ui_file *stream,
                = podata->end_bitpos
                  - type->field (i).type ()->length () * TARGET_CHAR_BIT;
            }
+         else if (strlen(type->field(i).name()) == 0)
+           /* crash: Print details for unnamed struct and union. */
+           newshow = show;
          c_print_type_1 (type->field (i).type (),
                          type->field (i).name (),
...
(I just pasted a section from the gdb-16.2.patch)
 diff --git a/extensions/eppic.mk b/extensions/eppic.mk
 index 9435793..b175df5 100644
 --- a/extensions/eppic.mk
 +++ b/extensions/eppic.mk
 @@ -53,7 +53,18 @@ all:
                         fi; \
                         if  [ -f $(APPFILE) ]; \
                         then \
 -                               make -f eppic.mk eppic.so; \
 +                               pushd eppic >/dev/null; \
 +                               if patch --dry-run -N -p0 < ../eppic.patch
 >/dev/null ; then \
 +                                       patch -N -p0 < ../eppic.patch; \
 +                                       popd >/dev/null; \
 +                                       make -f eppic.mk eppic.so; \
 +                               elif patch --dry-run -N -p0 -R <
 ../eppic.patch >/dev/null ; then \
 +                                       popd >/dev/null; \
 +                                       make -f eppic.mk eppic.so; \
 +                               else \
 +                                       popd >/dev/null; \
 +                                       echo "eppic.so: apply eppic.patch
 error"; \
 +                               fi; \
                         else \
                                 echo "eppic.so: failed to pull eppic code
 from git repo"; \
                         fi; \
 diff --git a/extensions/eppic.patch b/extensions/eppic.patch
 new file mode 100644
 index 0000000..9e43665
 --- /dev/null
 +++ b/extensions/eppic.patch
 @@ -0,0 +1,210 @@
 +--- applications/crash/eppic.c
 ++++ applications/crash/eppic.c
 +@@ -20,6 +20,7 @@
 + #include "defs.h"
 +
 + #include <eppic_api.h>
 ++#include "eppic.h"
 +
 + /*
 +  *  Global data (global_data.c)
 +@@ -788,6 +789,39 @@ char *sclass_help[]={
 +                 NULL
 + };
 +
 ++char *eppic_help[]={
 ++              "eppic",
 ++                "Run eppic program(es).",
 ++                "<fileName1.c>[, <fileName2.c>]",
 ++                "  Oneshot run eppic program(es) which with a main()
 entry each.",
 ++                NULL
 ++};
 ++
 ++void
 ++eppic_command(void)
 ++{
 ++      char *buf;
 ++      optind = 1;
 ++
 ++      if (!args[optind]) {
 ++              cmd_usage(crash_global_cmd(), SYNOPSIS);
 ++              return;
 ++      }
 ++
 ++      while(args[optind]) {
 ++              buf = eppic_filempath(args[optind]);
 ++              if (!buf) {
 ++                      eppic_msg("eppic_filempath error on %s\n",
 args[optind]);
 ++                      return;
 ++              }
 ++              eppic_load(buf);
 ++              if (eppic_findfile(buf, 0))
 ++                      eppic_unload(buf);
 ++              eppic_free(buf);
 ++              optind++;
 ++      }
 ++}
 ++
 + #define NCMDS 200
 + static struct command_table_entry command_table[NCMDS] =  {
 +
 +@@ -797,6 +831,7 @@ static struct command_table_entry
 command_table[NCMDS] =  {
 +       {"sdebug", sdebug_cmd, sdebug_help},
 +       {"sname", sname_cmd, sname_help},
 +       {"sclass", sclass_cmd, sclass_help},
 ++      {"eppic", eppic_command, eppic_help},
 +       {(char *)0 }
 + };
 +
 +@@ -885,6 +920,13 @@ char **help=malloc(sizeof *help * 5);
 +         }
 +     }
 +     free(help);
 ++
 ++    if (load && !strcmp(name, "main")) {
 ++        int optind_save = optind;
 ++        eppic_cmd(name, NULL, 0);
 ++        optind = optind_save;
 ++    }
 ++
 +     return;
 + }
 +
 +--- libeppic/eppic_api.h
 ++++ libeppic/eppic_api.h
 +@@ -16,6 +16,9 @@
 + /* minor and major version number
 +     4.0 switch to new Eppic name and use of fully typed symbols.
 + */
 ++#ifndef EPPIC_API_H
 ++#define EPPIC_API_H
 ++
 + #define S_MAJOR 5
 + #define S_MINOR 0
 +
 +@@ -298,3 +301,5 @@ void eppic_dbg_named(int class, char *name, int
 level, char *, ...);
 +
 + /* parsers debug flags */
 + extern int eppicdebug, eppicppdebug;
 ++
 ++#endif
 +\ No newline at end of file
 +--- libeppic/eppic_func.c
 ++++ libeppic/eppic_func.c
 +@@ -22,6 +22,8 @@
 + #include <sys/types.h>
 + #include <time.h>
 + #include <sys/stat.h>
 ++#include <fcntl.h>
 ++#include <unistd.h>
 + #include "eppic.h"
 +
 + /*
 +@@ -793,6 +795,42 @@ char *ed=getenv("EDITOR");
 +     if(!system(buf)) eppic_load(fname);
 + }
 +
 ++static const char *example[] = {
 ++"/*
      ",
 ++" * Example: Print all tasks' PID & command
      ",
 ++" *
      ",
 ++" * // Kernel's global variables and data structures can be used
 directly without",
 ++" * // pre-define it in kernel header. If any are within kernel modules,
 should",
 ++" * // preload the .ko first via \"mod -S/-s\" cmd in crash before
 invoke your",
 ++" * // eppic program.
      ",
 ++" * //
               ",
 ++" * // Eppic program's syntax is similar to C but with slight
 differences.    ",
 ++" * // Code samples:
       ",
 ++" * //
 
https://github.com/lucchouina/eppic/tree/master/applications/crash/code",
 ++" * // Available eppic functions:
      ",
 ++" * //
 
https://github.com/lucchouina/eppic/blob/master/libeppic/eppic_builtin.c#...
 ",
 ++" *
      ",
 ++" * int main(void)
       ",
 ++" * {
      ",
 ++" *     struct task_struct *p;
               ",
 ++" *     unsigned long offset;
      ",
 ++" *
      ",
 ++" *     p = (struct task_struct *)&init_task;
      ",
 ++" *     offset = (unsigned long)&(p->tasks) - (unsigned long)p;
      ",
 ++" *
      ",
 ++" *     do {
       ",
 ++" *         printf(\"PID: %d Command: %s\\n\", (int)(p->pid),
 getstr((char *)&(p->comm[0])));",
 ++" *         p = (struct task_struct *)((unsigned long)(p->tasks.next) -
 offset);",
 ++" *     } while(p != &init_task);
      ",
 ++" *
      ",
 ++" *     return 0;
      ",
 ++" * }
      ",
 ++" *
      ",
 ++" * crash> eppic program_file.c
      ",
 ++" */
       ",
 ++};
 
This looks very helpful.
Thanks
Lianbo
 ++
 ++char *eppic_get_func_file(char *);
 + /*
 +     This funciton is called to start a vi session on a function
 +     (file=0) or a file (file=1);
 +@@ -800,24 +838,31 @@ char *ed=getenv("EDITOR");
 + void
 + eppic_vi(char *fname, int file)
 + {
 +-int line, freeit=0;
 ++int line=1, freeit=0, fd;
 + char *filename;
 ++char newline = '\n';
 +
 +     if(file) {
 +
 +         filename=eppic_filempath(fname);
 +
 +         if(!filename) {
 +-
 +-            eppic_msg("File not found : %s\n", fname);
 +-            return;
 +-
 +-        }
 +-
 +-        line=1;
 +-        freeit=1;
 +-
 +-
 ++          fd = creat(fname, 0644);
 ++          if (fd < 0) {
 ++              eppic_msg("File not found : %s\n", fname);
 ++              return;
 ++          } else {
 ++              for (int i = 0; i < sizeof(example)/sizeof(char *); i++) {
 ++                      write(fd, example[i], strlen(example[i]));
 ++                      write(fd, &newline, sizeof(newline));
 ++              }
 ++              close(fd);
 ++              filename = fname;
 ++              freeit=0;
 ++          }
 ++        } else {
 ++            freeit=1;
 ++      }
 +     } else {
 +
 +         func *f=eppic_getfbyname(fname, 0);
 +@@ -837,6 +882,10 @@ char *filename;
 +
 +     eppic_exevi(filename, line);
 +
 ++    char *fi_name = eppic_get_func_file("main");
 ++    if (fi_name)
 ++        eppic_deletefile(fi_name);
 ++
 +     if(freeit) eppic_free(filename);
 +
 + }
 +@@ -1184,3 +1233,10 @@ eppic_runcmd(char *fname, var_t*args)
 +     return 0;
 + }
 +
 ++char *eppic_get_func_file(char *funcname)
 ++{
 ++      func *fn = eppic_getfbyname(funcname, 0);
 ++      if (!fn)
 ++              return NULL;
 ++      return fn->file->fname;
 ++}
 --
 2.47.0