* [PATCH v4 1/7] objtool/klp: Remove redundant strcmp() in correlate_symbols()
2026-03-05 23:15 [PATCH v4 0/7] objtool/klp: klp-build LTO support Song Liu
@ 2026-03-05 23:15 ` Song Liu
2026-03-05 23:15 ` [PATCH v4 2/7] objtool/klp: Remove trailing '_' in demangle_name() Song Liu
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Song Liu @ 2026-03-05 23:15 UTC (permalink / raw)
To: live-patching
Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
Song Liu
find_global_symbol_by_name() already compares names of the two symbols,
so there is no need to compare them again.
Signed-off-by: Song Liu <song@kernel.org>
---
tools/objtool/klp-diff.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index a3198a63c2f0..57606bc3390a 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -454,7 +454,7 @@ static int correlate_symbols(struct elfs *e)
sym2 = find_global_symbol_by_name(e->patched, sym1->name);
- if (sym2 && !sym2->twin && !strcmp(sym1->name, sym2->name)) {
+ if (sym2 && !sym2->twin) {
sym1->twin = sym2;
sym2->twin = sym1;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v4 2/7] objtool/klp: Remove trailing '_' in demangle_name()
2026-03-05 23:15 [PATCH v4 0/7] objtool/klp: klp-build LTO support Song Liu
2026-03-05 23:15 ` [PATCH v4 1/7] objtool/klp: Remove redundant strcmp() in correlate_symbols() Song Liu
@ 2026-03-05 23:15 ` Song Liu
2026-03-05 23:15 ` [PATCH v4 3/7] objtool/klp: Use sym->demangled_name for symbol_name hash Song Liu
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Song Liu @ 2026-03-05 23:15 UTC (permalink / raw)
To: live-patching
Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
Song Liu
With CONFIG_LTO_CLANG_THIN, it is possible to have nested __UNIQUE_ID_,
such as:
__UNIQUE_ID_addressable___UNIQUE_ID_pci_invalid_bar_694_695
To remove both trailing numbers, also remove trailing '_'.
Also add comments to demangle_name().
Signed-off-by: Song Liu <song@kernel.org>
---
tools/objtool/elf.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 2c02c7b49265..0d93e8496e8d 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -441,6 +441,19 @@ static int read_sections(struct elf *elf)
return 0;
}
+/*
+ * Remove number suffix of a symbol.
+ *
+ * Specifically, remove trailing numbers for "__UNIQUE_ID_" symbols and
+ * symbols with '.'.
+ *
+ * With CONFIG_LTO_CLANG_THIN, it is possible to have nested __UNIQUE_ID_,
+ * such as
+ *
+ * __UNIQUE_ID_addressable___UNIQUE_ID_pci_invalid_bar_694_695
+ *
+ * to remove both trailing numbers, also remove trailing '_'.
+ */
static const char *demangle_name(struct symbol *sym)
{
char *str;
@@ -463,7 +476,7 @@ static const char *demangle_name(struct symbol *sym)
for (int i = strlen(str) - 1; i >= 0; i--) {
char c = str[i];
- if (!isdigit(c) && c != '.') {
+ if (!isdigit(c) && c != '.' && c != '_') {
str[i + 1] = '\0';
break;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v4 3/7] objtool/klp: Use sym->demangled_name for symbol_name hash
2026-03-05 23:15 [PATCH v4 0/7] objtool/klp: klp-build LTO support Song Liu
2026-03-05 23:15 ` [PATCH v4 1/7] objtool/klp: Remove redundant strcmp() in correlate_symbols() Song Liu
2026-03-05 23:15 ` [PATCH v4 2/7] objtool/klp: Remove trailing '_' in demangle_name() Song Liu
@ 2026-03-05 23:15 ` Song Liu
2026-03-05 23:15 ` [PATCH v4 4/7] objtool/klp: Also demangle global objects Song Liu
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Song Liu @ 2026-03-05 23:15 UTC (permalink / raw)
To: live-patching
Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
Song Liu
For klp-build with LTO, it is necessary to correlate demangled symbols,
e.g., correlate foo.llvm.<num 1> and foo.llvm.<num 2>. However, these two
symbols do not have the same str_hash(name). To be able to correlate the
two symbols, calculate hash based on demanged_name, so that these two
symbols have the same hash.
No functional changes intended.
Signed-off-by: Song Liu <song@kernel.org>
---
tools/objtool/elf.c | 58 +++++++++++++++++++++++++++++++--------------
1 file changed, 40 insertions(+), 18 deletions(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 0d93e8496e8d..d9f883f7cff8 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -26,11 +26,18 @@
#include <objtool/elf.h>
#include <objtool/warn.h>
+static ssize_t demangled_name_len(const char *name);
+
static inline u32 str_hash(const char *str)
{
return jhash(str, strlen(str), 0);
}
+static inline u32 str_hash_demangled(const char *str)
+{
+ return jhash(str, demangled_name_len(str), 0);
+}
+
#define __elf_table(name) (elf->name##_hash)
#define __elf_bits(name) (elf->name##_bits)
@@ -294,7 +301,7 @@ static struct symbol *find_local_symbol_by_file_and_name(const struct elf *elf,
{
struct symbol *sym;
- elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(name)) {
+ elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash_demangled(name)) {
if (sym->bind == STB_LOCAL && sym->file == file &&
!strcmp(sym->name, name)) {
return sym;
@@ -308,7 +315,7 @@ struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *nam
{
struct symbol *sym;
- elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(name)) {
+ elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash_demangled(name)) {
if (!strcmp(sym->name, name) && !is_local_sym(sym))
return sym;
}
@@ -441,6 +448,28 @@ static int read_sections(struct elf *elf)
return 0;
}
+/*
+ * Returns desired length of the demangled name.
+ * If name doesn't need demangling, return strlen(name).
+ */
+static ssize_t demangled_name_len(const char *name)
+{
+ ssize_t idx;
+
+ if (!strstarts(name, "__UNIQUE_ID_") && !strchr(name, '.'))
+ return strlen(name);
+
+ for (idx = strlen(name) - 1; idx >= 0; idx--) {
+ char c = name[idx];
+
+ if (!isdigit(c) && c != '.' && c != '_')
+ break;
+ }
+ if (idx <= 0)
+ return strlen(name);
+ return idx + 1;
+}
+
/*
* Remove number suffix of a symbol.
*
@@ -457,6 +486,7 @@ static int read_sections(struct elf *elf)
static const char *demangle_name(struct symbol *sym)
{
char *str;
+ ssize_t len;
if (!is_local_sym(sym))
return sym->name;
@@ -464,24 +494,16 @@ static const char *demangle_name(struct symbol *sym)
if (!is_func_sym(sym) && !is_object_sym(sym))
return sym->name;
- if (!strstarts(sym->name, "__UNIQUE_ID_") && !strchr(sym->name, '.'))
+ len = demangled_name_len(sym->name);
+ if (len == strlen(sym->name))
return sym->name;
- str = strdup(sym->name);
+ str = strndup(sym->name, len);
if (!str) {
ERROR_GLIBC("strdup");
return NULL;
}
- for (int i = strlen(str) - 1; i >= 0; i--) {
- char c = str[i];
-
- if (!isdigit(c) && c != '.' && c != '_') {
- str[i + 1] = '\0';
- break;
- }
- }
-
return str;
}
@@ -517,9 +539,13 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
entry = &sym->sec->symbol_list;
list_add(&sym->list, entry);
+ sym->demangled_name = demangle_name(sym);
+ if (!sym->demangled_name)
+ return -1;
+
list_add_tail(&sym->global_list, &elf->symbols);
elf_hash_add(symbol, &sym->hash, sym->idx);
- elf_hash_add(symbol_name, &sym->name_hash, str_hash(sym->name));
+ elf_hash_add(symbol_name, &sym->name_hash, str_hash(sym->demangled_name));
if (is_func_sym(sym) &&
(strstarts(sym->name, "__pfx_") ||
@@ -543,10 +569,6 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
sym->pfunc = sym->cfunc = sym;
- sym->demangled_name = demangle_name(sym);
- if (!sym->demangled_name)
- return -1;
-
return 0;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v4 4/7] objtool/klp: Also demangle global objects
2026-03-05 23:15 [PATCH v4 0/7] objtool/klp: klp-build LTO support Song Liu
` (2 preceding siblings ...)
2026-03-05 23:15 ` [PATCH v4 3/7] objtool/klp: Use sym->demangled_name for symbol_name hash Song Liu
@ 2026-03-05 23:15 ` Song Liu
2026-03-05 23:15 ` [PATCH v4 5/7] objtool/klp: Remove .llvm suffix in demangle_name() Song Liu
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Song Liu @ 2026-03-05 23:15 UTC (permalink / raw)
To: live-patching
Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
Song Liu
With CONFIG_LTO_CLANG_THIN, it is possible to have global __UNIQUE_ID,
such as:
FUNC GLOBAL HIDDEN 19745 __UNIQUE_ID_quirk_amd_nb_node_458
Also demangle global objects.
Signed-off-by: Song Liu <song@kernel.org>
---
tools/objtool/elf.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index d9f883f7cff8..78db51ebbed4 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -488,9 +488,6 @@ static const char *demangle_name(struct symbol *sym)
char *str;
ssize_t len;
- if (!is_local_sym(sym))
- return sym->name;
-
if (!is_func_sym(sym) && !is_object_sym(sym))
return sym->name;
--
2.52.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v4 5/7] objtool/klp: Remove .llvm suffix in demangle_name()
2026-03-05 23:15 [PATCH v4 0/7] objtool/klp: klp-build LTO support Song Liu
` (3 preceding siblings ...)
2026-03-05 23:15 ` [PATCH v4 4/7] objtool/klp: Also demangle global objects Song Liu
@ 2026-03-05 23:15 ` Song Liu
2026-03-05 23:15 ` [PATCH v4 6/7] objtool/klp: Match symbols based on demangled_name for global variables Song Liu
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Song Liu @ 2026-03-05 23:15 UTC (permalink / raw)
To: live-patching
Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
Song Liu
Remove .llvm suffix, so that we can correlate foo.llvm.<hash 1> and
foo.llvm.<hash 2>.
Signed-off-by: Song Liu <song@kernel.org>
---
tools/objtool/elf.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 78db51ebbed4..51e6267cdf8d 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -455,6 +455,11 @@ static int read_sections(struct elf *elf)
static ssize_t demangled_name_len(const char *name)
{
ssize_t idx;
+ const char *p;
+
+ p = strstr(name, ".llvm.");
+ if (p)
+ return p - name;
if (!strstarts(name, "__UNIQUE_ID_") && !strchr(name, '.'))
return strlen(name);
@@ -482,6 +487,9 @@ static ssize_t demangled_name_len(const char *name)
* __UNIQUE_ID_addressable___UNIQUE_ID_pci_invalid_bar_694_695
*
* to remove both trailing numbers, also remove trailing '_'.
+ *
+ * For symbols with llvm suffix, i.e., foo.llvm.<hash>, remove the
+ * .llvm.<hash> part.
*/
static const char *demangle_name(struct symbol *sym)
{
--
2.52.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v4 6/7] objtool/klp: Match symbols based on demangled_name for global variables
2026-03-05 23:15 [PATCH v4 0/7] objtool/klp: klp-build LTO support Song Liu
` (4 preceding siblings ...)
2026-03-05 23:15 ` [PATCH v4 5/7] objtool/klp: Remove .llvm suffix in demangle_name() Song Liu
@ 2026-03-05 23:15 ` Song Liu
2026-03-05 23:15 ` [PATCH v4 7/7] objtool/klp: Correlate locals to globals Song Liu
2026-03-06 16:09 ` [PATCH v4 0/7] objtool/klp: klp-build LTO support Josh Poimboeuf
7 siblings, 0 replies; 9+ messages in thread
From: Song Liu @ 2026-03-05 23:15 UTC (permalink / raw)
To: live-patching
Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
Song Liu
correlate_symbols() will always try to match full name first. If there is
no match, try match only demangled_name.
In very rare cases, it is possible to have multiple foo.llvm.<hash> in
the same kernel. Whenever there is ambiguity like this, fail the klp diff.
Signed-off-by: Song Liu <song@kernel.org>
---
tools/objtool/elf.c | 13 +++++++
tools/objtool/include/objtool/elf.h | 3 ++
tools/objtool/klp-diff.c | 57 +++++++++++++++++++++++++++++
3 files changed, 73 insertions(+)
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 51e6267cdf8d..ef4affd6e45e 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -323,6 +323,19 @@ struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *nam
return NULL;
}
+void iterate_global_symbol_by_demangled_name(const struct elf *elf,
+ const char *demangled_name,
+ void (*process)(struct symbol *sym, void *data),
+ void *data)
+{
+ struct symbol *sym;
+
+ elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(demangled_name)) {
+ if (!strcmp(sym->demangled_name, demangled_name) && !is_local_sym(sym))
+ process(sym, data);
+ }
+}
+
struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
unsigned long offset, unsigned int len)
{
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index e12c516bd320..25573e5af76e 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -186,6 +186,9 @@ struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);
struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *name);
+void iterate_global_symbol_by_demangled_name(const struct elf *elf, const char *demangled_name,
+ void (*process)(struct symbol *sym, void *data),
+ void *data);
struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
int find_symbol_hole_containing(const struct section *sec, unsigned long offset);
struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 57606bc3390a..92043da0ed0b 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -355,6 +355,46 @@ static bool dont_correlate(struct symbol *sym)
strstarts(sym->name, "__initcall__");
}
+struct process_demangled_name_data {
+ struct symbol *ret;
+ int count;
+};
+
+static void process_demangled_name(struct symbol *sym, void *d)
+{
+ struct process_demangled_name_data *data = d;
+
+ if (sym->twin)
+ return;
+
+ data->count++;
+ data->ret = sym;
+}
+
+/*
+ * When there is no full name match, try match demangled_name. This would
+ * match original foo.llvm.123 to patched foo.llvm.456.
+ *
+ * Note that, in very rare cases, it is possible to have multiple
+ * foo.llvm.<hash> in the same kernel. When this happens, report error and
+ * fail the diff.
+ */
+static int find_global_symbol_by_demangled_name(struct elf *elf, struct symbol *sym,
+ struct symbol **out_sym)
+{
+ struct process_demangled_name_data data = {};
+
+ iterate_global_symbol_by_demangled_name(elf, sym->demangled_name,
+ process_demangled_name,
+ &data);
+ if (data.count > 1) {
+ ERROR("Multiple (%d) correlation candidates for %s", data.count, sym->name);
+ return -1;
+ }
+ *out_sym = data.ret;
+ return 0;
+}
+
/*
* For each symbol in the original kernel, find its corresponding "twin" in the
* patched kernel.
@@ -453,6 +493,23 @@ static int correlate_symbols(struct elfs *e)
continue;
sym2 = find_global_symbol_by_name(e->patched, sym1->name);
+ if (sym2 && !sym2->twin) {
+ sym1->twin = sym2;
+ sym2->twin = sym1;
+ }
+ }
+
+ /*
+ * Correlate globals with demangled_name.
+ * A separate loop is needed because we want to finish all the
+ * full name correlations first.
+ */
+ for_each_sym(e->orig, sym1) {
+ if (sym1->bind == STB_LOCAL || sym1->twin)
+ continue;
+
+ if (find_global_symbol_by_demangled_name(e->patched, sym1, &sym2))
+ return -1;
if (sym2 && !sym2->twin) {
sym1->twin = sym2;
--
2.52.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH v4 7/7] objtool/klp: Correlate locals to globals
2026-03-05 23:15 [PATCH v4 0/7] objtool/klp: klp-build LTO support Song Liu
` (5 preceding siblings ...)
2026-03-05 23:15 ` [PATCH v4 6/7] objtool/klp: Match symbols based on demangled_name for global variables Song Liu
@ 2026-03-05 23:15 ` Song Liu
2026-03-06 16:09 ` [PATCH v4 0/7] objtool/klp: klp-build LTO support Josh Poimboeuf
7 siblings, 0 replies; 9+ messages in thread
From: Song Liu @ 2026-03-05 23:15 UTC (permalink / raw)
To: live-patching
Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
Song Liu
Allow correlating original locals to patched globals, and vice versa.
This is needed when:
1. User adds/removes "static" for a function.
2. CONFIG_LTO_CLANG_THIN promotes local functions and objects to global
and add .llvm.<hash> suffix.
Signed-off-by: Song Liu <song@kernel.org>
---
tools/objtool/klp-diff.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 92043da0ed0b..7bdb2a417096 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -517,6 +517,36 @@ static int correlate_symbols(struct elfs *e)
}
}
+ /* Correlate original locals with patched globals */
+ for_each_sym(e->orig, sym1) {
+ if (sym1->twin || dont_correlate(sym1) || !is_local_sym(sym1))
+ continue;
+
+ sym2 = find_global_symbol_by_name(e->patched, sym1->name);
+ if (!sym2 && find_global_symbol_by_demangled_name(e->patched, sym1, &sym2))
+ return -1;
+
+ if (sym2 && !sym2->twin) {
+ sym1->twin = sym2;
+ sym2->twin = sym1;
+ }
+ }
+
+ /* Correlate original globals with patched locals */
+ for_each_sym(e->patched, sym2) {
+ if (sym2->twin || dont_correlate(sym2) || !is_local_sym(sym2))
+ continue;
+
+ sym1 = find_global_symbol_by_name(e->orig, sym2->name);
+ if (!sym1 && find_global_symbol_by_demangled_name(e->orig, sym2, &sym1))
+ return -1;
+
+ if (sym1 && !sym1->twin) {
+ sym2->twin = sym1;
+ sym1->twin = sym2;
+ }
+ }
+
for_each_sym(e->orig, sym1) {
if (sym1->twin || dont_correlate(sym1))
continue;
--
2.52.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH v4 0/7] objtool/klp: klp-build LTO support
2026-03-05 23:15 [PATCH v4 0/7] objtool/klp: klp-build LTO support Song Liu
` (6 preceding siblings ...)
2026-03-05 23:15 ` [PATCH v4 7/7] objtool/klp: Correlate locals to globals Song Liu
@ 2026-03-06 16:09 ` Josh Poimboeuf
7 siblings, 0 replies; 9+ messages in thread
From: Josh Poimboeuf @ 2026-03-06 16:09 UTC (permalink / raw)
To: Song Liu; +Cc: live-patching, jikos, mbenes, pmladek, joe.lawrence, kernel-team
On Thu, Mar 05, 2026 at 03:15:24PM -0800, Song Liu wrote:
> Add support for LTO in klp-build toolchain. The key changes are to the
> symbol correlation logic.Basically, we want to:
>
> 1. Match symbols with differerent .llvm.<hash> suffixes, e.g., foo.llvm.123
> to foo.llvm.456.
> 2. Match local symbols with promoted global symbols, e.g., local foo
> with global foo.llvm.123.
>
> 1/7 and 2/7 are small cleanup/fix for existing code.
> 3/7 through 7/7 contains the core logic changes to correlate_symbols().
>
> Changes v3 => v4:
> 1. Minor fixes in patches 1, 3, 7.
> 2. Only keep patches 1-7 for now, as there is ongoing discussion about the
> test infrastructure.
>
> Changes v2 => v3:
> 1. Fix a bug in global => local correlations (patch 7/8).
> 2. Remove a WARN().
> 3. Some empty line changes.
>
> Changes v1 => v2:
> 1. Error out on ambiguous .llvm.<hash>
>
> Song Liu (7):
> objtool/klp: Remove redundant strcmp() in correlate_symbols()
> objtool/klp: Remove trailing '_' in demangle_name()
> objtool/klp: Use sym->demangled_name for symbol_name hash
> objtool/klp: Also demangle global objects
> objtool/klp: Remove .llvm suffix in demangle_name()
> objtool/klp: Match symbols based on demangled_name for global
> variables
> objtool/klp: Correlate locals to globals
>
> tools/objtool/elf.c | 95 ++++++++++++++++++++++-------
> tools/objtool/include/objtool/elf.h | 3 +
> tools/objtool/klp-diff.c | 89 ++++++++++++++++++++++++++-
> 3 files changed, 165 insertions(+), 22 deletions(-)
Thanks! I will go ahead and queue these up.
--
Josh
^ permalink raw reply [flat|nested] 9+ messages in thread