Skip to contentSkip to conversation

makedumpfile security key filtering with eppic

PATCH Superseded Aravinda Prasad 2 participants 12 messages Dec 14, 2012 – Dec 27, 2012

Subsystems (3)

v3 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v3 cover makedumpfile security key filtering with eppic

makedumpfile security key filtering enhancement - Add Eppic language support (formerly known as SIAL) to specify rules to scrub data in a dumpfile. Eppic was previously part of crash source code repository.

The following series of patches enhance the makedumpfile to provide a more powerful way to specify rules and commands to traverse and erase complex data structures in a dump file by integrating Embeddable Pre-Processor and Interpreter for C (eppic).

Eppic is an interpreter that facilitates access to the symbol and type information stored in an executable image or a dump file. Eppic defines a language semantic which is similar to C. Eppic macros can be used to specify rules/commands to erase data in an image file. makedumpfile will interpret the rules/commands provided by eppic macros with the help of eppic library and will suitably erase the required data in a dump file. Eppic provides a lot of language constructs like conditional statements, logical and arithmetic operators, nested loops, functions, etc., to traverse nested lists and trees and conditionally erase data in the dump file, enabling users to literally erase any data in the dump file which is accessible through global symbols.

The series of patches integrates eppic with makdumpfile. These patches require eppic library libeppic.a and eppic_api.h header file. The libeppic.a library can be built from the eppic source code available at the following URL:

http://code.google.com/p/eppic/

TODO:

- Currently, works only for symbols in vmlinux, extend it to module symbols
- Functionality support:
- Implement the following callback functions.
- apialignment
- apigetenum
- apigetdefs
- Other functionalities specified in the code with TODO tag
- Support specifying eppic macros in makedumpfile.conf file
- Update erase info

Changelog from v2 to v3:
- Re-based to v1.5.1
- Removed EPPIC=on option from Makefile.
- Dynamically loads eppic shared object instead of statically linking
- Based on the discussion in the mailing list
- http://lists.infradead.org/pipermail/kexec/2012-December/007450.html
- Only patches 1 and 2 are modified

Changelog from v1 to v2:

- Re-based to v1.5.0
- Introduced EPPIC=on in makefile, and hence eppic is now optional
- Incorporated review comments from Atsushi
- Minor formatting changes

Regards,
Aravinda
---

Aravinda Prasad (7):
Initialize and setup eppic
makedumpfile and eppic interface layer
Eppic call back functions to query a dump image Implement apigetctype call back function Implement apimember and apigetrtype call back functions Extend eppic built-in functions to include memset function Support fully typed symbol access mode

 Makefile          |    5 -
 dwarf_info.c      |  367 +++++++++++++++++++++++++++++++++++++++++++
 dwarf_info.h      |   18 ++
 erase_info.c      |   91 ++++++++++-
 erase_info.h      |    1 
 extension_eppic.c |  451 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 extension_eppic.h |   75 +++++++++
 makedumpfile.c    |    7 +
 makedumpfile.h    |    6 +
 9 files changed, 1016 insertions(+), 5 deletions(-)
 create mode 100644 extension_eppic.c
 create mode 100644 extension_eppic.h
Signature · 7 lines
Aravinda Prasad


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#1 lore raw

PATCH v3 1/7 Initialize and setup eppic

This patch contains routines which initialize eppic and register call back function which will be called whenever a new eppic macro is loaded using eppic_load() API. The registered call back function executes the eppic macro as soon as it is loaded.

---
 Makefile          |    5 +++
 extension_eppic.c |   84 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 extension_eppic.h |   23 +++++++++++++++
 3 files changed, 111 insertions(+), 1 deletions(-)
 create mode 100644 extension_eppic.c
 create mode 100644 extension_eppic.h
Makefile +4 -1
index e6c4e5d..f123a5f 100644
@@ -69,7 +69,7 @@ $(OBJ_ARCH): $(SRC_ARCH)
 	$(CC) $(CFLAGS_ARCH) -c -o ./$@ ./$(@:.o=.c) 
 
 makedumpfile: $(SRC) $(OBJ_PART) $(OBJ_ARCH)
-	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ_PART) $(OBJ_ARCH) -o $@ $< $(LIBS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ_PART) $(OBJ_ARCH) -rdynamic -o $@ $< $(LIBS)
 	echo .TH MAKEDUMPFILE 8 \"$(DATE)\" \"makedumpfile v$(VERSION)\" \"Linux System Administrator\'s Manual\" > temp.8
 	grep -v "^.TH MAKEDUMPFILE 8" makedumpfile.8 >> temp.8
 	mv temp.8 makedumpfile.8
@@ -79,6 +79,9 @@ makedumpfile: $(SRC) $(OBJ_PART) $(OBJ_ARCH)
 	mv temp.5 makedumpfile.conf.5
 	gzip -c ./makedumpfile.conf.5 > ./makedumpfile.conf.5.gz
 
+eppic_makedumpfile.so: extension_eppic.c
+	$(CC) $(CFLAGS) -nostartfiles -shared -rdynamic -o $@ extension_eppic.c -fPIC -leppic
+
 clean:
 	rm -f $(OBJ) $(OBJ_PART) $(OBJ_ARCH) makedumpfile makedumpfile.8.gz makedumpfile.conf.5.gz
 
extension_eppic.c new file +84 -0

84 lines not on this page · raw message

extension_eppic.h new file +23 -0
new file mode 100644
index 0000000..ca74ce4
@@ -0,0 +1,23 @@
+/*
+ * extension_eppic.h
+ *
+ * Created by: Aravinda Prasad <[email protected]>
+ *
+ * Copyright (C) 2012  IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef _EXTENSION_EPPIC_H
+#define _EXTENSION_EPPIC_H
+
+#include "eppic_api.h"
+
+#endif /* _EXTENSION_EPPIC_H */

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#2 lore raw

Re: [PATCH v3 1/7] Initialize and setup eppic

Hello Aravinda,

Thank you for updating.
I have two comments in this mail.

Quoted 28 lines · On Fri, 14 Dec 2012 14:56:04 +0530 Aravinda Prasad…

This patch contains routines which initialize eppic and register call back function which will be called whenever a new eppic macro is loaded using eppic_load() API. The registered call back function executes the eppic macro as soon as it is loaded.

---
 Makefile          |    5 +++
 extension_eppic.c |   84 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 extension_eppic.h |   23 +++++++++++++++
 3 files changed, 111 insertions(+), 1 deletions(-)
 create mode 100644 extension_eppic.c
 create mode 100644 extension_eppic.h
Makefile +1 -1
index e6c4e5d..f123a5f 100644
@@ -69,7 +69,7 @@ $(OBJ_ARCH): $(SRC_ARCH)
 	$(CC) $(CFLAGS_ARCH) -c -o ./$@ ./$(@:.o=.c) 
 
 makedumpfile: $(SRC) $(OBJ_PART) $(OBJ_ARCH)
-	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ_PART) $(OBJ_ARCH) -o $@ $< $(LIBS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ_PART) $(OBJ_ARCH) -rdynamic -o $@ $< $(LIBS)
 	echo .TH MAKEDUMPFILE 8 \"$(DATE)\" \"makedumpfile v$(VERSION)\" \"Linux System Administrator\'s Manual\" > temp.8
 	grep -v "^.TH MAKEDUMPFILE 8" makedumpfile.8 >> temp.8
 	mv temp.8 makedumpfile.8

Makefile makedumpfile: $(SRC) $(OBJ_PART) $(OBJ_ARCH) · line 84

Quoted 6 lines
Makefile +3 -0
@@ -79,6 +79,9 @@ makedumpfile: $(SRC) $(OBJ_PART) $(OBJ_ARCH)
 	mv temp.5 makedumpfile.conf.5
 	gzip -c ./makedumpfile.conf.5 > ./makedumpfile.conf.5.gz
 
+eppic_makedumpfile.so: extension_eppic.c
+	$(CC) $(CFLAGS) -nostartfiles -shared -rdynamic -o $@ extension_eppic.c -fPIC -leppic
+

First, I prepared eppic_makedumpfile.so with the code above, but I failed with the message below:

  $ makedumpfile -cd31 -x vmlinux --eppic eppic_macro/mod.c vmcore dumpfile.cd31
  process_eppic_file: dlopen failed: /usr/lib64/eppic_makedumpfile.so: undefined symbol: setupterm

makedumpfile Failed.
$

so I think '-lncurses' should be specified as gcc option, or did I mistake ?

[...]

Quoted 6 lines
Makefile +6 -0
+/* Initialize eppic */
+int
+_init()
+{
+	if (eppic_open() >= 0) {
+

Makefile makedumpfile: $(SRC) $(OBJ_PART) $(OBJ_ARCH)

Quoted 10 lines
Makefile +10 -0
+		/* Register call back functions */
+		eppic_apiset(NULL, 3, sizeof(long), 0);
+
+		/* set the new function callback */
+		eppic_setcallback(reg_callback);
+
+		return 0;
+	}
+	return 1;
+}

Second, your code introduce _init() as constructor for dlopen(). I'm not sure about dlopen(), but I found the description which recommend not to use _init() in man page:

The obsolete symbols _init() and _fini()
The linker recognizes special symbols _init and _fini. If a dynamic library exports a routine named _init(), then that code is executed
after the loading, before dlopen() returns. If the dynamic library exports a routine named _fini(), then that routine is called just
before the library is unloaded. In case you need to avoid linking against the system startup files, this can be done by using the gcc(1) -nostartfiles command-line option.

Using these routines, or the gcc -nostartfiles or -nostdlib options, is not recommended. Their use may result in undesired behavior, since the constructor/destructor routines will not be executed (unless special measures are taken).

Instead, libraries should export routines using the __attribute__((constructor)) and __attribute__((destructor)) function attributes. See
the gcc info pages for information on these. Constructor routines are executed before dlopen() returns, and destructor routines are exe- cuted before dlclose() returns.

So, is it OK to continue to use _init() ?

BTW, would you send the patch to add the description of this feature to README, man page and help message ?

Thanks
Atsushi Kumagai

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#3 lore raw

Re: [PATCH v3 1/7] Initialize and setup eppic

Hi Atsushi,

Quoted 47 lines · Atsushi Kumagai

Hello Aravinda,

Thank you for updating.
I have two comments in this mail.

Quoted 28 lines · On Fri, 14 Dec 2012 14:56:04 +0530 Aravinda Prasad…

This patch contains routines which initialize eppic and register call back function which will be called whenever a new eppic macro is loaded using eppic_load() API. The registered call back function executes the eppic macro as soon as it is loaded.

---
 Makefile          |    5 +++
 extension_eppic.c |   84 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 extension_eppic.h |   23 +++++++++++++++
 3 files changed, 111 insertions(+), 1 deletions(-)
 create mode 100644 extension_eppic.c
 create mode 100644 extension_eppic.h
Makefile +1 -1
index e6c4e5d..f123a5f 100644
@@ -69,7 +69,7 @@ $(OBJ_ARCH): $(SRC_ARCH)
 	$(CC) $(CFLAGS_ARCH) -c -o ./$@ ./$(@:.o=.c) 
 
 makedumpfile: $(SRC) $(OBJ_PART) $(OBJ_ARCH)
-	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ_PART) $(OBJ_ARCH) -o $@ $< $(LIBS)
+	$(CC) $(CFLAGS) $(LDFLAGS) $(OBJ_PART) $(OBJ_ARCH) -rdynamic -o $@ $< $(LIBS)
 	echo .TH MAKEDUMPFILE 8 \"$(DATE)\" \"makedumpfile v$(VERSION)\" \"Linux System Administrator\'s Manual\" > temp.8
 	grep -v "^.TH MAKEDUMPFILE 8" makedumpfile.8 >> temp.8
 	mv temp.8 makedumpfile.8

Makefile makedumpfile: $(SRC) $(OBJ_PART) $(OBJ_ARCH) · line 84

Quoted 6 lines
Makefile +3 -0
@@ -79,6 +79,9 @@ makedumpfile: $(SRC) $(OBJ_PART) $(OBJ_ARCH)
 	mv temp.5 makedumpfile.conf.5
 	gzip -c ./makedumpfile.conf.5 > ./makedumpfile.conf.5.gz
 
+eppic_makedumpfile.so: extension_eppic.c
+	$(CC) $(CFLAGS) -nostartfiles -shared -rdynamic -o $@ extension_eppic.c -fPIC -leppic
+

First, I prepared eppic_makedumpfile.so with the code above, but I failed with the message below:

Quoted 7 lines
  $ makedumpfile -cd31 -x vmlinux --eppic eppic_macro/mod.c vmcore dumpfile.cd31
  process_eppic_file: dlopen failed: /usr/lib64/eppic_makedumpfile.so: undefined symbol: setupterm

makedumpfile Failed.
$

so I think '-lncurses' should be specified as gcc option, or did I mistake ?

-ltinfo was missing in the gcc option.

Quoted 31 lines

[...]

Quoted 6 lines
Makefile +6 -0
+/* Initialize eppic */
+int
+_init()
+{
+	if (eppic_open() >= 0) {
+

Makefile

Quoted 10 lines
Makefile +10 -0
+		/* Register call back functions */
+		eppic_apiset(NULL, 3, sizeof(long), 0);
+
+		/* set the new function callback */
+		eppic_setcallback(reg_callback);
+
+		return 0;
+	}
+	return 1;
+}

Second, your code introduce _init() as constructor for dlopen(). I'm not sure about dlopen(), but I found the description which recommend not to use _init() in man page:

The obsolete symbols _init() and _fini()
The linker recognizes special symbols _init and _fini. If a dynamic library exports a routine named _init(), then that code is executed
after the loading, before dlopen() returns. If the dynamic library exports a routine named _fini(), then that routine is called just
before the library is unloaded. In case you need to avoid linking against the system startup files, this can be done by using the gcc(1) -nostartfiles command-line option.

Quoted 8 lines

Using these routines, or the gcc -nostartfiles or -nostdlib options, is not recommended. Their use may result in undesired behavior, since the constructor/destructor routines will not be executed (unless special measures are taken).

Instead, libraries should export routines using the __attribute__((constructor)) and __attribute__((destructor)) function attributes. See
the gcc info pages for information on these. Constructor routines are executed before dlopen() returns, and destructor routines are exe- cuted before dlclose() returns.

So, is it OK to continue to use _init() ?

I am planning to change _init() to eppic_init() and then explicitly call it after dlopen(), as using _init() is not recommended.

Apart from this I am facing some minor issues with dlopen(). With static makedumpfile, dlopen is not able to resolve some symbols in dwarf_info.c and is failing, while it is working when compiled with LINKTYPE=dynamic. I am looking into it.

Quoted 13 lines

BTW, would you send the patch to add the description of this feature to README, man page and help message ?

Thanks
Atsushi Kumagai

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Signature · 8 lines
Regards,
Aravinda


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#4 lore raw

PATCH v3 2/7 makedumpfile and eppic interface layer

In reply to Aravinda Prasad

This patch extends the makedumpfile functionality to include eppic language support. The patch dynamically loads the makedumpfile specific shared object and calls the eppic_load function in shared object to load/compile and execute the specified eppic macros.

This patch also includes "--eppic" option to makedumpfile command to specify the eppic macro or the directory containing eppic macros. The specified eppic macro will be executed to scrub the data in the dumpfile. In case of a directory, all the eppic macros inside the directory will be executed for scrubbing the data.

TODO
- Support specifying eppic macros in the makedumpfile.conf file. A new command should be added to makedumpfile.conf to identify an eppic macro. This command could be used in any section of the makedumpfile.conf, where the section name indicates the kernel module name. makedumpfile will only search for symbols encountered by eppic macro only in the specified module. Because, searching these symbols in all the modules will cause huge performance overhead.

---
 erase_info.c      |   58 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 extension_eppic.h |    1 +
 makedumpfile.c    |    7 +++++-
 makedumpfile.h    |    6 +++++
 4 files changed, 69 insertions(+), 3 deletions(-)
erase_info.c +56 -2
index e2e6a52..0b6dcf4 100644
@@ -21,6 +21,8 @@
 #include "dwarf_info.h"
 #include "erase_info.h"
 
+#include <dlfcn.h>
+
 struct erase_info	*erase_info = NULL;
 unsigned long		num_erase_info = 1; /* Node 0 is unused. */
 
@@ -1811,6 +1813,48 @@ process_config_file(const char *name_config)
 	return TRUE;
 }
 
+
+/* Process the eppic macro using eppic library */
+static int
+process_eppic_file(char *name_config)
+{
+	void *handle;
+	void (*eppic_load)(char *), (*eppic_unload)(char *);
+
+	/*
+	 * Dynamically load the eppic_makedumpfile.so library.
+	 * Dynamically loading will cause _init function to be called
+	 */
+	handle = dlopen("eppic_makedumpfile.so", RTLD_LAZY | RTLD_GLOBAL);
+	if (!handle) {
+		ERRMSG("dlopen failed: %s\n", dlerror());
+		return FALSE;
+	}
+
+	/* TODO
+	 * Support specifying eppic macros in makedumpfile.conf file
+	 */
+
+	eppic_load = dlsym(handle, "eppic_load");
+	if (!eppic_load) {
+		ERRMSG("Could not find eppic_load function\n");
+		return FALSE;
+	}
+
+	eppic_unload = dlsym(handle, "eppic_unload");
+	if (!eppic_unload)
+		ERRMSG("Could not find eppic_unload function\n");
+
+	/* Load/compile, execute and unload the eppic macro */
+	eppic_load(name_config);
+	eppic_unload(name_config);
+
+	if (dlclose(handle))
+		ERRMSG("dlclose failed: %s\n", dlerror());
+
+	return TRUE;
+}
+
 static void
 split_filter_info(struct filter_info *prev, unsigned long long next_paddr,
 						size_t size)
@@ -1904,7 +1948,7 @@ extract_filter_info(unsigned long long start_paddr,
 int
 gather_filter_info(void)
 {
-	int ret;
+	int ret = TRUE;
 
 	/*
 	 * Before processing filter config file, load the symbol data of
@@ -1915,7 +1959,17 @@ gather_filter_info(void)
 	if (!load_module_symbols())
 		return FALSE;
 
-	ret = process_config_file(info->name_filterconfig);
+	/*
+	 * XXX: We support specifying both makedumpfile.conf and
+	 * eppic macro at the same time. Whether to retain or discard the
+	 * functionality provided by makedumpfile.conf is open for
+	 * discussion
+	 */
+	if (info->name_filterconfig)
+		ret = process_config_file(info->name_filterconfig);
+
+	if (info->name_eppic_config)
+		ret &= process_eppic_file(info->name_eppic_config);
 
 	/*
 	 * Remove modules symbol information, we dont need now.
extension_eppic.h +1 -0
index ca74ce4..34396e4 100644
@@ -21,3 +21,4 @@
 #include "eppic_api.h"
 
 #endif /* _EXTENSION_EPPIC_H */
+
makedumpfile.c +6 -1
index 314dc46..087f556 100644
@@ -7330,7 +7330,8 @@ retry:
 		}
 	}
 
-	if (info->name_filterconfig && !gather_filter_info())
+	if ((info->name_filterconfig || info->name_eppic_config)
+			&& !gather_filter_info())
 		return FALSE;
 
 	if (!create_dump_bitmap())
@@ -8228,6 +8229,7 @@ static struct option longopts[] = {
 	{"diskset", required_argument, NULL, 'k'},
 	{"non-cyclic", no_argument, NULL, 'Y'},
 	{"cyclic-buffer", required_argument, NULL, 'Z'},
+	{"eppic", required_argument, NULL, 'S'},
 	{0, 0, 0, 0}
 };
 
@@ -8326,6 +8328,9 @@ main(int argc, char *argv[])
 		case 's':
 			info->flag_split = 1;
 			break;
+		case 'S':
+			info->name_eppic_config = optarg;
+			break;
 		case 'r':
 			info->flag_reassemble = 1;
 			break;
makedumpfile.h +6 -0
index d2bdc0c..a9b7680 100644
@@ -905,6 +905,12 @@ struct DumpInfo {
 	FILE		*file_filterconfig;
 
 	/*
+	 * Filter config file containing eppic language filtering rules
+	 * to filter out kernel data from vmcore
+	 */
+	char		*name_eppic_config;
+
+	/*
 	 * diskdimp info:
 	 */
 	int		block_order;

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#5 lore raw

PATCH v3 3/7 Eppic call back functions to query a dump image

In reply to Aravinda Prasad

This patch implements a series of apigetuint* call back functions which are used to access data from the dump image. Eppic uses these call back functions to fetch the actual value of the global variables.

This patch also adds other call back functions as a place holder which will be implemented in later patches. This is mainly to avoid compilation error while registering the call back functions using eppic_apiset() function.

---
 extension_eppic.c |  128 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 extension_eppic.h |   49 ++++++++++++++++++++
 2 files changed, 175 insertions(+), 2 deletions(-)
extension_eppic.c +127 -1
index 48a3cbe..774d16e 100644
@@ -20,6 +20,7 @@
 #include <sys/types.h>
 #include <fcntl.h>
 
+#include "makedumpfile.h"
 #include "extension_eppic.h"
 
 /*
@@ -64,6 +65,131 @@ reg_callback(char *name, int load)
 	return;
 }
 
+/*
+ * Call back functions for eppic to query the dump image
+ */
+
+static int
+apigetmem(ull iaddr, void *p, int nbytes)
+{
+	return readmem(VADDR, iaddr, p, nbytes);
+}
+
+static int
+apiputmem(ull iaddr, void *p, int nbytes)
+{
+	return 1;
+}
+
+static char *
+apimember(char *mname, ull pidx, type_t *tm,
+		member_t *m, ull *lidx)
+{
+	return 0;
+}
+
+static int
+apigetctype(int ctype, char *name, type_t *tout)
+{
+	return 0;
+}
+
+static char *
+apigetrtype(ull idx, type_t *t)
+{
+	return "";
+}
+
+static int
+apialignment(ull idx)
+{
+	return 0;
+}
+
+int
+apigetval(char *name, ull *val, VALUE_S *value)
+{
+	ull ptr = 0;
+
+	ptr = get_symbol_addr(name);
+	if (!ptr)
+		return 0;
+
+	*val = ptr;
+	return 1;
+}
+
+static enum_t *
+apigetenum(char *name)
+{
+	return 0;
+}
+
+static def_t *
+apigetdefs(void)
+{
+	return 0;
+}
+
+static uint8_t
+apigetuint8(void *ptr)
+{
+	uint8_t val;
+	if (!readmem(VADDR, (unsigned long)ptr, (char *)&val, sizeof(val)))
+		return (uint8_t) -1;
+	return val;
+}
+
+static uint16_t
+apigetuint16(void *ptr)
+{
+	uint16_t val;
+	if (!readmem(VADDR, (unsigned long)ptr, (char *)&val, sizeof(val)))
+		return (uint16_t) -1;
+	return val;
+}
+
+static uint32_t
+apigetuint32(void *ptr)
+{
+	uint32_t val;
+	if (!readmem(VADDR, (unsigned long)ptr, (char *)&val, sizeof(val)))
+		return (uint32_t) -1;
+	return val;
+}
+
+static uint64_t
+apigetuint64(void *ptr)
+{
+	uint64_t val;
+	if (!readmem(VADDR, (unsigned long)ptr, (char *)&val, sizeof(val)))
+		return (uint64_t) -1;
+	return val;
+}
+
+static char *
+apifindsym(char *p)
+{
+	return NULL;
+}
+
+apiops icops = {
+	apigetmem,
+	apiputmem,
+	apimember,
+	apigetctype,
+	apigetrtype,
+	apialignment,
+	apigetval,
+	apigetenum,
+	apigetdefs,
+	apigetuint8,
+	apigetuint16,
+	apigetuint32,
+	apigetuint64,
+	apifindsym
+};
+
 
 /* Initialize eppic */
 int
@@ -72,7 +198,7 @@ _init()
 	if (eppic_open() >= 0) {
 
 		/* Register call back functions */
-		eppic_apiset(NULL, 3, sizeof(long), 0);
+		eppic_apiset(&icops, 3, sizeof(long), 0);
 
 		/* set the new function callback */
 		eppic_setcallback(reg_callback);
extension_eppic.h +48 -1

53 lines not on this page · raw message

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#6 lore raw

PATCH v3 4/7 Implement apigetctype call back function

In reply to Aravinda Prasad

libeppic will call apigetctype call back function whenever it encounters a token in the eppic macro. The call back function will use DWARF to query information related to the requested token and will pass it back to eppic using libeppic API calls. If the token does not exist, then apigetctype call returns 0.

---
 dwarf_info.c      |  109 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 dwarf_info.h      |    9 ++++
 extension_eppic.c |   28 +++++++++++++-
 3 files changed, 145 insertions(+), 1 deletions(-)
dwarf_info.c +109 -0
index 09a8e1e..a8a87e1 100644
@@ -51,6 +51,7 @@ struct dwarf_info {
 	long	enum_number;		/* OUT */
 	unsigned char	type_flag;	/* OUT */
 	char	src_name[LEN_SRCFILE];	/* OUT */
+	Dwarf_Off die_offset;		/* OUT */
 };
 static struct dwarf_info	dwarf_info;
 
@@ -102,6 +103,22 @@ is_search_typedef(int cmd)
 }
 
 static int
+is_search_domain(int cmd)
+{
+	if ((cmd == DWARF_INFO_GET_DOMAIN_STRUCT)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_TYPEDEF)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_ARRAY)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_UNION)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_ENUM)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_REF)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_STRING)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_BASE))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static int
 process_module (Dwfl_Module *dwflmod,
 		void **userdata __attribute__ ((unused)),
 		const char *name __attribute__ ((unused)),
@@ -750,6 +767,74 @@ search_symbol(Dwarf_Die *die, int *found)
 }
 
 static void
+search_domain(Dwarf_Die *die, int *found)
+{
+	int tag;
+	const char *name;
+	short flag = 0;
+	Dwarf_Die die_type;
+
+	do {
+		tag  = dwarf_tag(die);
+		name = dwarf_diename(die);
+
+		/*
+		 * Descend into members and search for the
+		 * needed domain there.
+		 */
+		if (!name) {
+			if (!get_die_type(die, &die_type))
+				continue;
+
+			if (is_container(&die_type)) {
+				Dwarf_Die child;
+
+				if (dwarf_child(&die_type, &child) != 0)
+					continue;
+
+				search_domain(&child, found);
+
+				if (*found)
+					return;
+			}
+		}
+
+		if ((!name) || strcmp(name, dwarf_info.symbol_name))
+			continue;
+
+		switch (dwarf_info.cmd) {
+		case DWARF_INFO_GET_DOMAIN_STRUCT:
+			if (tag == DW_TAG_structure_type)
+				flag = 1;
+			break;
+		case DWARF_INFO_GET_DOMAIN_UNION:
+			if (tag == DW_TAG_union_type)
+				flag = 1;
+			break;
+		case DWARF_INFO_GET_DOMAIN_TYPEDEF:
+			if (tag == DW_TAG_typedef)
+				flag = 1;
+			break;
+		/* TODO
+		 * Implement functionality for the rest of the domains
+		 */
+		}
+
+		if (!flag)
+			continue;
+
+		dwarf_info.struct_size = dwarf_bytesize(die);
+
+		if (dwarf_info.struct_size > 0) {
+			if (found)
+				*found = TRUE;
+			dwarf_info.die_offset = dwarf_dieoffset(die);
+			break;
+		}
+	} while (!dwarf_siblingof(die, die));
+}
+
+static void
 search_die_tree(Dwarf_Die *die, int *found)
 {
 	Dwarf_Die child;
@@ -774,6 +859,9 @@ search_die_tree(Dwarf_Die *die, int *found)
 
 	else if (is_search_typedef(dwarf_info.cmd))
 		search_typedef(die, found);
+
+	else if (is_search_domain(dwarf_info.cmd))
+		search_domain(die, found);
 }
 
 static int
@@ -1166,6 +1254,27 @@ get_source_filename(char *structname, char *src_name, int cmd)
 }
 
 /*
+ * Get the domain information of the symbol
+ */
+long
+get_domain(char *symname, int cmd, unsigned long long *die)
+{
+	dwarf_info.cmd         = cmd;
+	dwarf_info.symbol_name = symname;
+	dwarf_info.type_name   = NULL;
+	dwarf_info.struct_size = NOT_FOUND_STRUCTURE;
+	dwarf_info.die_offset  = 0;
+
+	if (!get_debug_info())
+		return 0;
+
+	if (die)
+		*die = (unsigned long long) dwarf_info.die_offset;
+
+	return dwarf_info.struct_size;
+}
+
+/*
  * Set the dwarf_info with kernel/module debuginfo file information.
  */
 int
dwarf_info.h +9 -0
index 185cbb6..074b5cc 100644
@@ -47,6 +47,14 @@ enum {
 	DWARF_INFO_GET_SYMBOL_TYPE,
 	DWARF_INFO_GET_MEMBER_TYPE,
 	DWARF_INFO_GET_ENUMERATION_TYPE_SIZE,
+	DWARF_INFO_GET_DOMAIN_STRUCT,
+	DWARF_INFO_GET_DOMAIN_TYPEDEF,
+	DWARF_INFO_GET_DOMAIN_ARRAY,
+	DWARF_INFO_GET_DOMAIN_UNION,
+	DWARF_INFO_GET_DOMAIN_ENUM,
+	DWARF_INFO_GET_DOMAIN_REF,
+	DWARF_INFO_GET_DOMAIN_STRING,
+	DWARF_INFO_GET_DOMAIN_BASE,
 };
 
 char *get_dwarf_module_name(void);
@@ -61,6 +69,7 @@ char *get_member_type_name(char *structname, char *membername, int cmd, long *si
 long get_array_length(char *name01, char *name02, unsigned int cmd);
 long get_enum_number(char *enum_name);
 int get_source_filename(char *structname, char *src_name, int cmd);
+long get_domain(char *symname, int cmd, unsigned long long *die);
 int set_dwarf_debuginfo(char *mod_name, char *os_release, char *name_debuginfo, int fd_debuginfo);
 
 #endif  /* DWARF_INFO_H */
extension_eppic.c +27 -1
index 774d16e..3fa3e88 100644
@@ -91,7 +91,33 @@ apimember(char *mname, ull pidx, type_t *tm,
 static int
 apigetctype(int ctype, char *name, type_t *tout)
 {
-	return 0;
+	long size = 0;
+	unsigned long long die = 0;
+
+	switch (ctype) {
+	case V_TYPEDEF:
+		size = get_domain(name, DWARF_INFO_GET_DOMAIN_TYPEDEF, &die);
+		break;
+	case V_STRUCT:
+		size = get_domain(name, DWARF_INFO_GET_DOMAIN_STRUCT, &die);
+		break;
+	case V_UNION:
+		size = get_domain(name, DWARF_INFO_GET_DOMAIN_UNION, &die);
+		break;
+	/* TODO
+	 * Implement for all the domains
+	 */
+	}
+
+	if (size <= 0 || !die)
+		return 0;
+
+	/* populate */
+	eppic_type_settype(tout, ctype);
+	eppic_type_setsize(tout, size);
+	eppic_type_setidx(tout, (ull)(unsigned long)die);
+	eppic_pushref(tout, 0);
+	return 1;
 }
 
 static char *

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#7 lore raw

Re: [PATCH v3 4/7] Implement apigetctype call back function

Hello Aravinda,

Quoted 76 lines · On Fri, 14 Dec 2012 14:56:32 +0530 Aravinda Prasad…

libeppic will call apigetctype call back function whenever it encounters a token in the eppic macro. The call back function will use DWARF to query information related to the requested token and will pass it back to eppic using libeppic API calls. If the token does not exist, then apigetctype call returns 0.

---
 dwarf_info.c      |  109 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 dwarf_info.h      |    9 ++++
 extension_eppic.c |   28 +++++++++++++-
 3 files changed, 145 insertions(+), 1 deletions(-)
dwarf_info.c +41 -0
index 09a8e1e..a8a87e1 100644
@@ -51,6 +51,7 @@ struct dwarf_info {
 	long	enum_number;		/* OUT */
 	unsigned char	type_flag;	/* OUT */
 	char	src_name[LEN_SRCFILE];	/* OUT */
+	Dwarf_Off die_offset;		/* OUT */
 };
 static struct dwarf_info	dwarf_info;
 
@@ -102,6 +103,22 @@ is_search_typedef(int cmd)
 }
 
 static int
+is_search_domain(int cmd)
+{
+	if ((cmd == DWARF_INFO_GET_DOMAIN_STRUCT)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_TYPEDEF)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_ARRAY)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_UNION)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_ENUM)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_REF)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_STRING)
+		|| (cmd == DWARF_INFO_GET_DOMAIN_BASE))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static int
 process_module (Dwfl_Module *dwflmod,
 		void **userdata __attribute__ ((unused)),
 		const char *name __attribute__ ((unused)),
@@ -750,6 +767,74 @@ search_symbol(Dwarf_Die *die, int *found)
 }
 
 static void
+search_domain(Dwarf_Die *die, int *found)
+{
+	int tag;
+	const char *name;
+	short flag = 0;
+	Dwarf_Die die_type;
+
+	do {
+		tag  = dwarf_tag(die);
+		name = dwarf_diename(die);
+
+		/*
+		 * Descend into members and search for the
+		 * needed domain there.
+		 */
+		if (!name) {
+			if (!get_die_type(die, &die_type))
+				continue;
+
+			if (is_container(&die_type)) {
+				Dwarf_Die child;
+
+				if (dwarf_child(&die_type, &child) != 0)
+					continue;

dwarf_info.c search_symbol(Dwarf_Die *die, int *found) · line 803

Quoted 10 lines
dwarf_info.c +10 -0
+
+				search_domain(&child, found);
+
+				if (*found)
+					return;
+			}
+		}
+
+		if ((!name) || strcmp(name, dwarf_info.symbol_name))
+			continue;

I commented for search_domain() in v1 patch:

http://lists.infradead.org/pipermail/kexec/2012-October/007024.html

Quoted 3 lines

I assume that search_domain() needs to descend into struct/union for a nested member, like how we fixed search_member() in commit:ecff242c. I want to make sure that your patches can treat even a nested member.

And I still think so, it should be fixed as below:

dwarf_info.c +1 -1
index 22c9e2f..a11b6ad 100644
@@ -814,7 +814,7 @@ search_domain(Dwarf_Die *die, int *found)
                 * Descend into members and search for the
                 * needed domain there.
                 */
-               if (!name) {
+               if ((!name) || strcmp(name, dwarf_info.symbol_name)) {
                        if (!get_die_type(die, &die_type))
                                continue;
 

Do you agree with me ?

Thanks
Atsushi Kumagai

Quoted 132 lines
dwarf_info.c +58 -0
+
+		switch (dwarf_info.cmd) {
+		case DWARF_INFO_GET_DOMAIN_STRUCT:
+			if (tag == DW_TAG_structure_type)
+				flag = 1;
+			break;
+		case DWARF_INFO_GET_DOMAIN_UNION:
+			if (tag == DW_TAG_union_type)
+				flag = 1;
+			break;
+		case DWARF_INFO_GET_DOMAIN_TYPEDEF:
+			if (tag == DW_TAG_typedef)
+				flag = 1;
+			break;
+		/* TODO
+		 * Implement functionality for the rest of the domains
+		 */
+		}
+
+		if (!flag)
+			continue;
+
+		dwarf_info.struct_size = dwarf_bytesize(die);
+
+		if (dwarf_info.struct_size > 0) {
+			if (found)
+				*found = TRUE;
+			dwarf_info.die_offset = dwarf_dieoffset(die);
+			break;
+		}
+	} while (!dwarf_siblingof(die, die));
+}
+
+static void
 search_die_tree(Dwarf_Die *die, int *found)
 {
 	Dwarf_Die child;
@@ -774,6 +859,9 @@ search_die_tree(Dwarf_Die *die, int *found)
 
 	else if (is_search_typedef(dwarf_info.cmd))
 		search_typedef(die, found);
+
+	else if (is_search_domain(dwarf_info.cmd))
+		search_domain(die, found);
 }
 
 static int
@@ -1166,6 +1254,27 @@ get_source_filename(char *structname, char *src_name, int cmd)
 }
 
 /*
+ * Get the domain information of the symbol
+ */
+long
+get_domain(char *symname, int cmd, unsigned long long *die)
+{
+	dwarf_info.cmd         = cmd;
+	dwarf_info.symbol_name = symname;
+	dwarf_info.type_name   = NULL;
+	dwarf_info.struct_size = NOT_FOUND_STRUCTURE;
+	dwarf_info.die_offset  = 0;
+
+	if (!get_debug_info())
+		return 0;
+
+	if (die)
+		*die = (unsigned long long) dwarf_info.die_offset;
+
+	return dwarf_info.struct_size;
+}
+
+/*
  * Set the dwarf_info with kernel/module debuginfo file information.
  */
 int
dwarf_info.h +9 -0
index 185cbb6..074b5cc 100644
@@ -47,6 +47,14 @@ enum {
 	DWARF_INFO_GET_SYMBOL_TYPE,
 	DWARF_INFO_GET_MEMBER_TYPE,
 	DWARF_INFO_GET_ENUMERATION_TYPE_SIZE,
+	DWARF_INFO_GET_DOMAIN_STRUCT,
+	DWARF_INFO_GET_DOMAIN_TYPEDEF,
+	DWARF_INFO_GET_DOMAIN_ARRAY,
+	DWARF_INFO_GET_DOMAIN_UNION,
+	DWARF_INFO_GET_DOMAIN_ENUM,
+	DWARF_INFO_GET_DOMAIN_REF,
+	DWARF_INFO_GET_DOMAIN_STRING,
+	DWARF_INFO_GET_DOMAIN_BASE,
 };
 
 char *get_dwarf_module_name(void);
@@ -61,6 +69,7 @@ char *get_member_type_name(char *structname, char *membername, int cmd, long *si
 long get_array_length(char *name01, char *name02, unsigned int cmd);
 long get_enum_number(char *enum_name);
 int get_source_filename(char *structname, char *src_name, int cmd);
+long get_domain(char *symname, int cmd, unsigned long long *die);
 int set_dwarf_debuginfo(char *mod_name, char *os_release, char *name_debuginfo, int fd_debuginfo);
 
 #endif  /* DWARF_INFO_H */
extension_eppic.c +20 -1
index 774d16e..3fa3e88 100644
@@ -91,7 +91,33 @@ apimember(char *mname, ull pidx, type_t *tm,
 static int
 apigetctype(int ctype, char *name, type_t *tout)
 {
-	return 0;
+	long size = 0;
+	unsigned long long die = 0;
+
+	switch (ctype) {
+	case V_TYPEDEF:
+		size = get_domain(name, DWARF_INFO_GET_DOMAIN_TYPEDEF, &die);
+		break;
+	case V_STRUCT:
+		size = get_domain(name, DWARF_INFO_GET_DOMAIN_STRUCT, &die);
+		break;
+	case V_UNION:
+		size = get_domain(name, DWARF_INFO_GET_DOMAIN_UNION, &die);
+		break;
+	/* TODO
+	 * Implement for all the domains
+	 */
+	}
+
+	if (size <= 0 || !die)
+		return 0;

extension_eppic.c apimember(char *mname, ull pidx, type_t *tm, · line 123

Quoted 10 lines
extension_eppic.c +7 -0
+
+	/* populate */
+	eppic_type_settype(tout, ctype);
+	eppic_type_setsize(tout, size);
+	eppic_type_setidx(tout, (ull)(unsigned long)die);
+	eppic_pushref(tout, 0);
+	return 1;
 }
 
 static char *

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#8 lore raw

Re: [PATCH v3 4/7] Implement apigetctype call back function

Hi Atsushi,

Quoted 5 lines · Atsushi Kumagai

Hello Aravinda,

On Fri, 14 Dec 2012 14:56:32 +0530
Aravinda Prasad <[email protected]> wrote:

[...]

Quoted 24 lines

I commented for search_domain() in v1 patch:

http://lists.infradead.org/pipermail/kexec/2012-October/007024.html

Quoted 3 lines

I assume that search_domain() needs to descend into struct/union for a nested member, like how we fixed search_member() in commit:ecff242c. I want to make sure that your patches can treat even a nested member.

And I still think so, it should be fixed as below:

dwarf_info.c +1 -1
index 22c9e2f..a11b6ad 100644
@@ -814,7 +814,7 @@ search_domain(Dwarf_Die *die, int *found)
                 * Descend into members and search for the
                 * needed domain there.
                 */
-               if (!name) {
+               if ((!name) || strcmp(name, dwarf_info.symbol_name)) {
                        if (!get_die_type(die, &die_type))
                                continue;
 
Quoted 1 line

Do you agree with me ?

Yes, I think this should be fine. I will modify and test the patch with the above change.

Quoted 148 lines

Thanks
Atsushi Kumagai

Quoted 142 lines
(quoted diff) +58 -0
+
+		switch (dwarf_info.cmd) {
+		case DWARF_INFO_GET_DOMAIN_STRUCT:
+			if (tag == DW_TAG_structure_type)
+				flag = 1;
+			break;
+		case DWARF_INFO_GET_DOMAIN_UNION:
+			if (tag == DW_TAG_union_type)
+				flag = 1;
+			break;
+		case DWARF_INFO_GET_DOMAIN_TYPEDEF:
+			if (tag == DW_TAG_typedef)
+				flag = 1;
+			break;
+		/* TODO
+		 * Implement functionality for the rest of the domains
+		 */
+		}
+
+		if (!flag)
+			continue;
+
+		dwarf_info.struct_size = dwarf_bytesize(die);
+
+		if (dwarf_info.struct_size > 0) {
+			if (found)
+				*found = TRUE;
+			dwarf_info.die_offset = dwarf_dieoffset(die);
+			break;
+		}
+	} while (!dwarf_siblingof(die, die));
+}
+
+static void
 search_die_tree(Dwarf_Die *die, int *found)
 {
 	Dwarf_Die child;
@@ -774,6 +859,9 @@ search_die_tree(Dwarf_Die *die, int *found)
 
 	else if (is_search_typedef(dwarf_info.cmd))
 		search_typedef(die, found);
+
+	else if (is_search_domain(dwarf_info.cmd))
+		search_domain(die, found);
 }
 
 static int
@@ -1166,6 +1254,27 @@ get_source_filename(char *structname, char *src_name, int cmd)
 }
 
 /*
+ * Get the domain information of the symbol
+ */
+long
+get_domain(char *symname, int cmd, unsigned long long *die)
+{
+	dwarf_info.cmd         = cmd;
+	dwarf_info.symbol_name = symname;
+	dwarf_info.type_name   = NULL;
+	dwarf_info.struct_size = NOT_FOUND_STRUCTURE;
+	dwarf_info.die_offset  = 0;
+
+	if (!get_debug_info())
+		return 0;
+
+	if (die)
+		*die = (unsigned long long) dwarf_info.die_offset;
+
+	return dwarf_info.struct_size;
+}
+
+/*
  * Set the dwarf_info with kernel/module debuginfo file information.
  */
 int
dwarf_info.h +9 -0
index 185cbb6..074b5cc 100644
@@ -47,6 +47,14 @@ enum {
 	DWARF_INFO_GET_SYMBOL_TYPE,
 	DWARF_INFO_GET_MEMBER_TYPE,
 	DWARF_INFO_GET_ENUMERATION_TYPE_SIZE,
+	DWARF_INFO_GET_DOMAIN_STRUCT,
+	DWARF_INFO_GET_DOMAIN_TYPEDEF,
+	DWARF_INFO_GET_DOMAIN_ARRAY,
+	DWARF_INFO_GET_DOMAIN_UNION,
+	DWARF_INFO_GET_DOMAIN_ENUM,
+	DWARF_INFO_GET_DOMAIN_REF,
+	DWARF_INFO_GET_DOMAIN_STRING,
+	DWARF_INFO_GET_DOMAIN_BASE,
 };
 
 char *get_dwarf_module_name(void);
@@ -61,6 +69,7 @@ char *get_member_type_name(char *structname, char *membername, int cmd, long *si
 long get_array_length(char *name01, char *name02, unsigned int cmd);
 long get_enum_number(char *enum_name);
 int get_source_filename(char *structname, char *src_name, int cmd);
+long get_domain(char *symname, int cmd, unsigned long long *die);
 int set_dwarf_debuginfo(char *mod_name, char *os_release, char *name_debuginfo, int fd_debuginfo);
 
 #endif  /* DWARF_INFO_H */
extension_eppic.c +27 -1
index 774d16e..3fa3e88 100644
@@ -91,7 +91,33 @@ apimember(char *mname, ull pidx, type_t *tm,
 static int
 apigetctype(int ctype, char *name, type_t *tout)
 {
-	return 0;
+	long size = 0;
+	unsigned long long die = 0;
+
+	switch (ctype) {
+	case V_TYPEDEF:
+		size = get_domain(name, DWARF_INFO_GET_DOMAIN_TYPEDEF, &die);
+		break;
+	case V_STRUCT:
+		size = get_domain(name, DWARF_INFO_GET_DOMAIN_STRUCT, &die);
+		break;
+	case V_UNION:
+		size = get_domain(name, DWARF_INFO_GET_DOMAIN_UNION, &die);
+		break;
+	/* TODO
+	 * Implement for all the domains
+	 */
+	}
+
+	if (size <= 0 || !die)
+		return 0;
+
+	/* populate */
+	eppic_type_settype(tout, ctype);
+	eppic_type_setsize(tout, size);
+	eppic_type_setidx(tout, (ull)(unsigned long)die);
+	eppic_pushref(tout, 0);
+	return 1;
 }
 
 static char *
Signature · 8 lines
Regards,
Aravinda


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#9 lore raw

PATCH v3 5/7 Implement apimember and apigetrtype call back functions

In reply to Aravinda Prasad

The patch includes functionality for apimember and apigetrtype eppic callback routines along with helper functions to fetch information related to the member of the structure/union

Whenever a structure/union member is accessed inside the eppic macro, eppic will query makedumpfile through call back functions requesting more information on the structure or union member. The information includes member name, offset from structure, data type and size. makedumpfile will get all these information using DWARF and pass back to eppic using libeppic API calls.

---
 dwarf_info.c      |  206 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 dwarf_info.h      |    7 ++
 extension_eppic.c |  179 +++++++++++++++++++++++++++++++++++++++++++++-
 extension_eppic.h |    2 +
 4 files changed, 390 insertions(+), 4 deletions(-)
dwarf_info.c +206 -0
index a8a87e1..f66d351 100644
@@ -463,6 +463,29 @@ get_dwarf_base_type(Dwarf_Die *die)
 	return TRUE;
 }
 
+/*
+ * Get the die, given the offset
+ */
+static int
+get_die_from_offset(Dwarf_Off offset, Dwarf_Die *die)
+{
+	if (!init_dwarf_info())
+		return FALSE;
+
+	if ((!offset) || (!die))
+		return FALSE;
+
+	if (!dwarf_offdie(dwarf_info.dwarfd, offset, die)) {
+		ERRMSG("Can't find the DIE.\n");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+/*
+ * Function for searching struct page.union.struct.mapping.
+ */
 static int
 is_container(Dwarf_Die *die)
 {
@@ -1275,6 +1298,189 @@ get_domain(char *symname, int cmd, unsigned long long *die)
 }
 
 /*
+ * Get the number of fields in a structure or union provided the
+ * die offset of the structure or union
+ */
+int
+get_die_nfields(unsigned long long die_off)
+{
+	int tag, nfields = 0;
+	Dwarf_Die result, child, *die;
+
+	if (!get_die_from_offset((Dwarf_Off) die_off, &result)) {
+		ERRMSG("Can't find the DIE.\n");
+		return -1;
+	}
+
+	die = &result;
+	tag = dwarf_tag(die);
+	if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
+		ERRMSG("DIE is not of structure or union type.\n");
+		return -1;
+	}
+
+	if (dwarf_child(die, &child) != 0)
+		return -1;
+
+	/* Find the number of fields in the structure */
+	die = &child;
+	do {
+		tag = dwarf_tag(die);
+		if (tag == DW_TAG_member)
+			nfields++;
+		else
+			continue;
+	} while (!dwarf_siblingof(die, die));
+
+	return nfields;
+}
+
+/*
+ * Get the information of the structure member given by index
+ */
+int
+get_die_member(unsigned long long die_off, int index, long *offset,
+		char **name, int *nbits, int *fbits, unsigned long long *m_die)
+{
+	int tag, size, nfields = 0;
+	Dwarf_Die result, child, die_base, *die;
+
+	if (!offset || !nbits || !fbits || !name || !m_die)
+		return -1;
+
+	if (!get_die_from_offset((Dwarf_Off) die_off, &result)) {
+		ERRMSG("Can't find the DIE.\n");
+		return -1;
+	}
+
+	die = &result;
+	tag = dwarf_tag(die);
+	if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) {
+		ERRMSG("DIE is not of structure or union type.\n");
+		return -1;
+	}
+
+	if (dwarf_child(die, &child) != 0)
+		return -1;
+
+	/* Find the correct field in the structure */
+	die = &child;
+	do {
+		tag = dwarf_tag(die);
+		if (tag == DW_TAG_member) {
+			if (nfields == index)
+				break;
+			else
+				nfields++;
+		}
+	} while (!dwarf_siblingof(die, die));
+
+	if (nfields != index) {
+		ERRMSG("No member found at index %d.\n", index);
+		return -1;
+	}
+
+	/* Fill in the required info for the member */
+	if (!get_data_member_location(die, offset))
+		*offset = 0;
+
+	*name = dwarf_diename(die);
+	*m_die = dwarf_dieoffset(die);
+
+	get_die_type(die, &die_base);
+	if (dwarf_tag(&die_base) == DW_TAG_array_type) {
+		dwarf_info.array_length = 0;
+		get_data_array_length(die);
+		size = dwarf_info.array_length;
+	} else {
+		size = dwarf_bytesize(&die_base);
+	}
+
+	/* TODO
+	 * Correctly update fbits and nbits
+	 */
+	*nbits = *fbits = 0;
+
+	if (size < 0)
+		return 0;
+	else
+		return size;
+}
+
+/*
+ * Get the die attribute type
+ */
+int
+get_die_attr_type(unsigned long long die_off, int *type_flag,
+		unsigned long long *die_attr_off)
+{
+	Dwarf_Die result;
+
+	if (!die_attr_off)
+		return FALSE;
+
+	if (!get_die_from_offset((Dwarf_Off) die_off, &result)) {
+		ERRMSG("Can't find the DIE.\n");
+		return FALSE;
+	}
+
+	if (!get_die_type(&result, &result))
+		return FALSE;
+
+	*die_attr_off = dwarf_dieoffset(&result);
+	*type_flag = dwarf_tag(&result);
+	return TRUE;
+}
+
+/*
+ * Get name attribute given the die offset
+ */
+char *
+get_die_name(unsigned long long die_off)
+{
+	Dwarf_Die result;
+
+	if (!die_off)
+		return NULL;
+
+	if (!get_die_from_offset((Dwarf_Off) die_off, &result)) {
+		ERRMSG("Can't find the DIE.\n");
+		return NULL;
+	}
+
+	return dwarf_diename(&result);
+}
+
+/*
+ * Get length attribute given the die offset
+ */
+int
+get_die_length(unsigned long long die_off, int flag)
+{
+	Dwarf_Die result, die_base;
+
+	if (!die_off)
+		return FALSE;
+
+	if (!get_die_from_offset((Dwarf_Off) die_off, &result)) {
+		ERRMSG("Can't find the DIE.\n");
+		return FALSE;
+	}
+
+	if (flag)
+		return dwarf_bytesize(&result);
+
+	get_die_type(&result, &die_base);
+	if (dwarf_tag(&die_base) == DW_TAG_array_type) {
+		dwarf_info.array_length = 0;
+		get_data_array_length(&result);
+		return dwarf_info.array_length;
+	} else {
+		return dwarf_bytesize(&die_base);
+	}
+}
+
+/*
  * Set the dwarf_info with kernel/module debuginfo file information.
  */
 int
dwarf_info.h +7 -0
index 074b5cc..d1d15a9 100644
@@ -70,6 +70,13 @@ long get_array_length(char *name01, char *name02, unsigned int cmd);
 long get_enum_number(char *enum_name);
 int get_source_filename(char *structname, char *src_name, int cmd);
 long get_domain(char *symname, int cmd, unsigned long long *die);
+int get_die_nfields(unsigned long long die_off);
+int get_die_member(unsigned long long die_off, int index, long *offset,
+	char **name, int *nbits, int *fbits, unsigned long long *m_die);
+int get_die_attr_type(unsigned long long die_off, int *type_flag,
+	unsigned long long *die_attr_off);
+char *get_die_name(unsigned long long die_off);
+int get_die_length(unsigned long long die_off, int flag);
 int set_dwarf_debuginfo(char *mod_name, char *os_release, char *name_debuginfo, int fd_debuginfo);
 
 #endif  /* DWARF_INFO_H */
extension_eppic.c +175 -4

208 lines not on this page · raw message

extension_eppic.h +2 -0
index beb68e4..15d7efc 100644
@@ -27,6 +27,8 @@
  * for makedumpfile extension.
  */
 
+#define MAX_ARRAY_DIMENSION 16
+
 /* member information */
 typedef MEMBER_S {
 

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#10 lore raw

PATCH v3 6/7 Extend eppic built-in functions to include memset function

In reply to Aravinda Prasad

The memset function will be used to specify the virtual address and the length of the data to be scrubbed in the dump file from the eppic macro. makedumpfile will convert these requests into filter_info nodes which will be enqueued for filtering. Existing makedumpfile functionality reads the filter_info nodes and scrubs the data accordingly.

---
 erase_info.c      |   33 ++++++++++++++++++++++++++++++++-
 erase_info.h      |    1 +
 extension_eppic.c |   20 ++++++++++++++++++++
 extension_eppic.h |    2 ++
 4 files changed, 55 insertions(+), 1 deletions(-)
erase_info.c +32 -1
index 0b6dcf4..cd365b1 100644
@@ -68,6 +68,8 @@ struct filter_info {
 	int			erase_info_idx;	/* 0= invalid index */
 	int			size_idx;
 
+	int			erase_ch;
+
 	struct filter_info      *next;
 	unsigned short          nullify;
 };
@@ -1576,6 +1578,7 @@ update_filter_info(struct config_entry *filter_symbol,
 	fl_info->paddr   = vaddr_to_paddr(sym_addr);
 	fl_info->size    = size;
 	fl_info->nullify = filter_symbol->nullify;
+	fl_info->erase_ch = 'X';
 
 	if (insert_filter_info(fl_info)) {
 		fl_info->erase_info_idx = add_erase_info_node(filter_symbol);
@@ -1584,6 +1587,34 @@ update_filter_info(struct config_entry *filter_symbol,
 	return TRUE;
 }
 
+int
+update_filter_info_raw(unsigned long long sym_addr, int ch, int len)
+{
+	struct filter_info *fl_info;
+
+	fl_info = calloc(1, sizeof(struct filter_info));
+	if (fl_info == NULL) {
+		ERRMSG("Can't allocate filter info\n");
+		return FALSE;
+	}
+
+	fl_info->vaddr   = sym_addr;
+	fl_info->paddr   = vaddr_to_paddr(sym_addr);
+	fl_info->size    = len;
+	fl_info->nullify = 0;
+	fl_info->erase_ch = ch;
+
+	if (insert_filter_info(fl_info)) {
+		/* TODO
+		 * Add support to update erase information to the
+		 * resulting dump file
+		 */
+		fl_info->erase_info_idx = 0;
+		fl_info->size_idx = 0;
+	}
+	return TRUE;
+}
+
 static int
 initialize_iteration_entry(struct config_entry *ie,
 				char *type_name, unsigned char type_flag)
@@ -2022,7 +2053,7 @@ filter_data_buffer(unsigned char *buf, unsigned long long paddr,
 		if (fl_info.nullify)
 			memset(buf_ptr, 0, fl_info.size);
 		else
-			memset(buf_ptr, 'X', fl_info.size);
+			memset(buf_ptr, fl_info.erase_ch, fl_info.size);
 	}
 }
 
erase_info.h +1 -0
index 636fcfa..2a9c43d 100644
@@ -38,6 +38,7 @@ int gather_filter_info(void);
 void clear_filter_info(void);
 void filter_data_buffer(unsigned char *buf, unsigned long long paddr, size_t size);
 unsigned long get_size_eraseinfo(void);
+int update_filter_info_raw(unsigned long long, int, int);
 
 #endif /* _ERASE_INFO_H */
 
extension_eppic.c +20 -0
index 8d0027f..85dfdcd 100644
@@ -387,6 +387,22 @@ apiops icops = {
 	apifindsym
 };
 
+/* Extensions to built-in functions */
+VALUE_S *
+eppic_memset(VALUE_S *vaddr, VALUE_S *vch, VALUE_S *vlen)
+{
+	ull addr = eppic_getval(vaddr);
+	int len = eppic_getval(vlen);
+	int ch = eppic_getval(vch);
+
+	/*
+	 * Set the value at address from iaddr till iaddr + nbytes
+	 * to the value specified in variable ch
+	 */
+	update_filter_info_raw(addr, ch, len);
+	return eppic_makebtype(1);
+}
+
 
 /* Initialize eppic */
 int
@@ -400,6 +416,10 @@ _init()
 		/* set the new function callback */
 		eppic_setcallback(reg_callback);
 
+		/* Extend built-in functions to include memset */
+		eppic_builtin("int memset(char *, int, int)",
+				(bf_t *)eppic_memset);
+
 		return 0;
 	}
 	return 1;
extension_eppic.h +2 -0
index 15d7efc..0a53646 100644
@@ -70,4 +70,6 @@ typedef TYPE_S {
 	ull rtype;  /* type_t a reference refers too */
 } type_t;
 
+extern int update_filter_info_raw(unsigned long long, int, int);
+
 #endif /* _EXTENSION_EPPIC_H */

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#11 lore raw

PATCH v3 7/7 Support fully typed symbol access mode

In reply to Aravinda Prasad

Eppic enables access to symbols in two ways. The first, is a more natural mode in that it makes symbols available as fully typed entities. The second, is generic and treats all symbols as an address to data which then needs to be cast to the proper type explicitly. The former obviously enables an easier cut & pasting of target code into eppic code.

Currently generic symbol access mode is supported. This patch extends the functionality to include support for fully typed symbol access mode (which will be the default mode) in eppic macros. User can switch to generic symbol access mode by setting the following environmental variable - EPPIC_LEGACY_MODE. libeppic.a will take care of handling EPPIC_LEGACY_MODE. libeppic.a will pass NULL to VALUE_S* argument of apigetval() call back function if EPPIC_LEGACY_MODE is set.

Refer to http://code.google.com/p/eppic/ for more information.

---
 dwarf_info.c      |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 dwarf_info.h      |    2 ++
 extension_eppic.c |   24 ++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 0 deletions(-)
dwarf_info.c +52 -0
index f66d351..22c9e2f 100644
@@ -119,6 +119,15 @@ is_search_domain(int cmd)
 }
 
 static int
+is_search_die(int cmd)
+{
+	if (cmd == DWARF_INFO_GET_DIE)
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static int
 process_module (Dwfl_Module *dwflmod,
 		void **userdata __attribute__ ((unused)),
 		const char *name __attribute__ ((unused)),
@@ -858,6 +867,25 @@ search_domain(Dwarf_Die *die, int *found)
 }
 
 static void
+search_die(Dwarf_Die *die, int *found)
+{
+	const char *name;
+
+	do {
+		name = dwarf_diename(die);
+
+		if ((!name) || strcmp(name, dwarf_info.symbol_name))
+			continue;
+
+		if (found)
+			*found = TRUE;
+
+		dwarf_info.die_offset = dwarf_dieoffset(die);
+		return;
+	} while (!dwarf_siblingof(die, die));
+}
+
+static void
 search_die_tree(Dwarf_Die *die, int *found)
 {
 	Dwarf_Die child;
@@ -885,6 +913,9 @@ search_die_tree(Dwarf_Die *die, int *found)
 
 	else if (is_search_domain(dwarf_info.cmd))
 		search_domain(die, found);
+
+	else if (is_search_die(dwarf_info.cmd))
+		search_die(die, found);
 }
 
 static int
@@ -1452,6 +1483,27 @@ get_die_name(unsigned long long die_off)
 }
 
 /*
+ * Get the die offset given the die name
+ */
+unsigned long long
+get_die_offset(char *sysname)
+{
+	dwarf_info.cmd         = DWARF_INFO_GET_DIE;
+	dwarf_info.symbol_name = sysname;
+	dwarf_info.type_name   = NULL;
+	dwarf_info.struct_size = NOT_FOUND_STRUCTURE;
+	dwarf_info.die_offset  = 0;
+
+	if (!sysname)
+		return 0;
+
+	if (!get_debug_info())
+		return 0;
+
+	return (unsigned long long)dwarf_info.die_offset;
+}
+
+/*
  * Get length attribute given the die offset
  */
 int
dwarf_info.h +2 -0
index d1d15a9..c5128f2 100644
@@ -55,6 +55,7 @@ enum {
 	DWARF_INFO_GET_DOMAIN_REF,
 	DWARF_INFO_GET_DOMAIN_STRING,
 	DWARF_INFO_GET_DOMAIN_BASE,
+	DWARF_INFO_GET_DIE,
 };
 
 char *get_dwarf_module_name(void);
@@ -76,6 +77,7 @@ int get_die_member(unsigned long long die_off, int index, long *offset,
 int get_die_attr_type(unsigned long long die_off, int *type_flag,
 	unsigned long long *die_attr_off);
 char *get_die_name(unsigned long long die_off);
+unsigned long long get_die_offset(char *sysname);
 int get_die_length(unsigned long long die_off, int flag);
 int set_dwarf_debuginfo(char *mod_name, char *os_release, char *name_debuginfo, int fd_debuginfo);
 
extension_eppic.c +24 -0
index 85dfdcd..835bd2d 100644
@@ -313,6 +313,30 @@ apigetval(char *name, ull *val, VALUE_S *value)
 		return 0;
 
 	*val = ptr;
+
+	if (!value)
+		return 1;
+
+	/* Support for fully typed symbol access */
+	ull type;
+	TYPE_S *stype;
+
+	type = get_die_offset(name);
+	stype = eppic_gettype(value);
+
+	apigetrtype(type, stype);
+
+	eppic_pushref(stype, 1);
+	eppic_setmemaddr(value, *val);
+	eppic_do_deref(1, value, value);
+
+	*val = eppic_getval(value);
+
+	if (!eppic_typeislocal(stype) && eppic_type_getidx(stype) > 100) {
+		char *tname = get_die_name(eppic_type_getidx(stype));
+		if (tname)
+			eppic_chktype(stype, tname);
+	}
 	return 1;
 }
 

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec