summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2014-08-04 15:09:39 +1000
committerChris Johns <chrisj@rtems.org>2014-08-04 15:09:39 +1000
commit13ee8dc9506807fd3fb253b52583611754cb719e (patch)
treee197a0ace5845ba04a1865e038983175e146f8a9
parent81534626cc87c4c6b050f9166c0c75fd61d3d53e (diff)
rtems-tld: Add generator loading support.
-rw-r--r--rld-config.cpp33
-rw-r--r--rld-config.h11
-rw-r--r--rld.h46
-rw-r--r--rtems-tld.cpp83
-rw-r--r--rtld-base.ini36
-rw-r--r--test-trace.ini3
6 files changed, 183 insertions, 29 deletions
diff --git a/rld-config.cpp b/rld-config.cpp
index b197e5d..af85f94 100644
--- a/rld-config.cpp
+++ b/rld-config.cpp
@@ -56,6 +56,28 @@ namespace rld
throw error ("not found", "config record: " + this->name + '/' + name);
}
+ std::string
+ section::get_record_item (const std::string& rec_name) const
+ {
+ const record& rec = get_record (rec_name);
+ if (rec.items.size () != 1)
+ throw rld::error ("duplicate", "record item: " + name + '/' + rec_name);
+ return rec.items[0].text;
+ }
+
+ void
+ section::get_record_items (const std::string& rec_name, rld::strings& items) const
+ {
+ const record& rec = get_record (rec_name);
+ items.clear ();
+ for (rld::config::items::const_iterator ii = rec.items.begin ();
+ ii != rec.items.end ();
+ ++ii)
+ {
+ items.push_back ((*ii).text);
+ }
+ }
+
config::config()
{
}
@@ -134,7 +156,8 @@ namespace rld
try
{
- const rld::config::record& rec = sec.get_record ("include");
+ rld::strings is;
+ parse_items (sec, "include", is);
have_includes = true;
@@ -147,11 +170,11 @@ namespace rld
* APIs.
*/
- for (rld::config::items::const_iterator ri = rec.items.begin ();
- ri != rec.items.end ();
- ++ri)
+ for (rld::strings::const_iterator isi = is.begin ();
+ isi != is.end ();
+ ++isi)
{
- load ((*ri).text);
+ load (*isi);
}
}
catch (rld::error re)
diff --git a/rld-config.h b/rld-config.h
index eb6d614..adf3a9e 100644
--- a/rld-config.h
+++ b/rld-config.h
@@ -90,6 +90,17 @@ namespace rld
* Find a record and throw an error if not found.
*/
const record& get_record (const std::string& name) const;
+
+ /**
+ * Return the single item in a record. If the record is duplicated an
+ * error is thrown.
+ */
+ std::string get_record_item (const std::string& name) const;
+
+ /**
+ * Return the list of items in a record in a strings container.
+ */
+ void get_record_items (const std::string& name, rld::strings& items) const;
};
/**
diff --git a/rld.h b/rld.h
index 70a6913..726a8e1 100644
--- a/rld.h
+++ b/rld.h
@@ -150,6 +150,37 @@ namespace rld
}
/**
+ * Dequote a string.
+ */
+ inline std::string dequote (const std::string& s)
+ {
+ if ((s.front () == '"') || (s.front () == '\''))
+ {
+ if (s.front () != s.back ())
+ throw rld::error ("invalid quoting", "string: " + s);
+ return s.substr (1, s.length () - (1 + 1));
+ }
+ return s;
+ }
+
+ /**
+ * Find and replace.
+ */
+ inline std::string find_replace(const std::string& sin,
+ const std::string& out,
+ const std::string& in)
+ {
+ std::string s = sin;
+ size_t pos = 0;
+ while ((pos = s.find (out, pos)) != std::string::npos)
+ {
+ s.replace (pos, out.length (), in);
+ pos += in.length ();
+ }
+ return s;
+ }
+
+ /**
* Split the string in a contain of strings based on the the
* delimiter. Optionally trim any white space or include empty string.
*
@@ -170,14 +201,7 @@ namespace rld
if (strip_whitespace)
trim (e);
if (strip_quotes)
- {
- if ((e.front () == '"') || (e.front () == '\''))
- {
- if (e.front () != e.back ())
- throw rld::error ("invalid quoting", "string: " + s);
- e = e.substr (1, e.length () - (1 + 1));
- }
- }
+ e = dequote (e);
if (empty || !e.empty ())
{
se.push_back (e);
@@ -189,10 +213,10 @@ namespace rld
/**
* Join the strings together with the separator.
*/
- inline std::string& join (const strings& ss,
- const std::string& separator,
- std::string& s)
+ inline std::string join (const strings& ss,
+ const std::string& separator)
{
+ std::string s;
for (strings::const_iterator ssi = ss.begin ();
ssi != ss.end ();
++ssi)
diff --git a/rtems-tld.cpp b/rtems-tld.cpp
index ede5d10..8765dca 100644
--- a/rtems-tld.cpp
+++ b/rtems-tld.cpp
@@ -109,10 +109,14 @@ namespace rld
*/
struct wrapper
{
- std::string name; /**< The name of this wrapper. */
- rld::strings headers; /**< Include statements. */
- rld::strings defines; /**< Define statements. */
- function_sigs sigs; /**< The functions this wrapper wraps. */
+ std::string name; /**< The name of this wrapper. */
+ rld::strings headers; /**< Include statements. */
+ rld::strings defines; /**< Define statements. */
+ std::string map_sym_prefix; /**< Mapping symbol prefix. */
+ std::string arg_trace; /**< Code template to trace an argument. */
+ std::string ret_trace; /**< Code template to trace the return value. */
+ std::string code; /**< Code block inserted before the trace code. */
+ function_sigs sigs; /**< The functions this wrapper wraps. */
/**
* Load the wrapper.
@@ -121,6 +125,12 @@ namespace rld
rld::config::config& config);
/**
+ * Parse the generator.
+ */
+ void parse_generator (rld::config::config& config,
+ const rld::config::section& section);
+
+ /**
* Recursive parser for strings.
*/
void parse (rld::config::config& config,
@@ -162,10 +172,10 @@ namespace rld
private:
- std::string name; /**< The name of the trace. */
- std::string bsp; /**< The BSP we are linking to. */
- rld::strings trace; /**< The functions to trace. */
- wrappers wrappers; /**< Wrappers wrap trace functions. */
+ std::string name; /**< The name of the trace. */
+ std::string bsp; /**< The BSP we are linking to. */
+ rld::strings trace; /**< The functions to trace. */
+ wrappers wrappers; /**< Wrappers wrap trace functions. */
};
/**
@@ -262,9 +272,13 @@ namespace rld
/*
* A wrapper section optionally contain one or more records of:
*
- * # header A list of include string that are single or double quoted.
- * # define A list of define string that are single or double quoted.
- * # signature A list of section names of function signatures.
+ * # trace A list of functions to trace.
+ * # generator The name of the generator section. Defaults if not present.
+ * # headers A list of sections containing headers or header records.
+ * # header A list of include string that are single or double quoted.
+ * # defines A list of sections containing defines or define record.
+ * # defines A list of define string that are single or double quoted.
+ * # signatures A list of section names of function signatures.
*
* @note The quoting and list spliting is a little weak because a delimiter
* in a quote should not be seen as a delimiter.
@@ -274,6 +288,8 @@ namespace rld
parse (config, section, "headers", "header", headers);
parse (config, section, "defines", "define", defines);
+ parse_generator (config, section);
+
rld::strings sig_list;
rld::config::parse_items (section, "signatures", sig_list);
@@ -294,6 +310,44 @@ namespace rld
}
void
+ wrapper::parse_generator (rld::config::config& config,
+ const rld::config::section& section)
+ {
+ const rld::config::record* rec = 0;
+ try
+ {
+ const rld::config::record& record = section.get_record ("generator");
+ rec = &record;
+ }
+ catch (rld::error re)
+ {
+ /*
+ * No error, continue.
+ */
+ }
+
+ std::string gen_section;
+
+ if (rec)
+ {
+ if (!rec->single ())
+ throw rld::error ("duplicate", "generator: " + section.name + "/generator");
+ gen_section = rec->items[0].text;
+ }
+ else
+ {
+ gen_section = config.get_section ("default-generator").get_record_item ("generator");
+ }
+
+ const rld::config::section& sec = config.get_section (gen_section);
+
+ map_sym_prefix = sec.get_record_item ("map-sym-prefix");
+ arg_trace = rld::dequote (sec.get_record_item ("arg-trace"));
+ ret_trace = rld::dequote (sec.get_record_item ("ret-trace"));
+ code = rld::dequote (sec.get_record_item ("code"));
+ }
+
+ void
wrapper::parse (rld::config::config& config,
const rld::config::section& section,
const std::string& sec_name,
@@ -337,7 +391,12 @@ namespace rld
{
out << " " << (*di) << std::endl;
}
- out << " Function Signatures: " << sigs.size () << std::endl;
+ out << " Mapping Symbol Prefix: " << map_sym_prefix << std::endl
+ << " Arg Trace Code: " << arg_trace << std::endl
+ << " Return Trace Code: " << ret_trace << std::endl
+ << " Code: | "
+ << rld::find_replace (code, "\n", "\n | ") << std::endl
+ << " Function Signatures: " << sigs.size () << std::endl;
for (function_sigs::const_iterator si = sigs.begin ();
si != sigs.end ();
++si)
diff --git a/rtld-base.ini b/rtld-base.ini
new file mode 100644
index 0000000..1ffc17e
--- /dev/null
+++ b/rtld-base.ini
@@ -0,0 +1,36 @@
+;
+; RTEMS Trace Linker Base configuration.
+;
+; Copyright 2014 Chris Johns <chrisj@rtems.org>
+;
+
+;
+; The default generartor is used if a wrapper does provide a generator record.
+;
+[default-generator]
+generator = printf-generator
+
+;
+; A printf generator prints to stdout the trace functions.
+;
+[printf-generator]
+map-sym-prefix = rtld_pg__
+headers = printf-generator-headers
+arg-trace = "rtld_pg_print_arg(@ARG_NUM@, @ARG_TYPE@, @ARG_SIZE@, &@ARG_LABEL@);"
+ret-trace = "rtld_pg_print_ret(@RET_TYPE@, @RETG_SIZE@, &@RET_LABEL@);"
+code = <<<CODE
+static inline void rtld_pg_print_arg(int arg_num,
+ const char* arg_type,
+ int arg_size,
+ void* arg
+{
+ const char* p = arg;
+ int i;
+ printf (" %2d] %s(%d) = ", arg_num, arg_type, arg_size);
+ for (i = 0; i < arg_size; ++i, ++p) printf ("%02x", (unsigned int) *p);
+ printf ("\n");
+}
+CODE
+
+[base-generator-headers]
+header = "#include <stdio.h>"
diff --git a/test-trace.ini b/test-trace.ini
index b4e2306..ae0a2de 100644
--- a/test-trace.ini
+++ b/test-trace.ini
@@ -23,7 +23,7 @@ wrapper = test-trace, rtems-api
;
; Include RTEMS Trace support.
;
-include = rtems.ini
+include = rtems.ini, rtld-base.ini
;
; User application trace example.
@@ -36,6 +36,7 @@ trace = test_trace_3
header = '#include "test-trace.h"'
define = "#define TEST_TRACE 1"
signatures = test-signatures
+generator = printf-generator
[test-headers]
header = '#include "test-trace.h"'