[PATCH 2/3] scripts/sorttable: Build ORC fast lookup table via sorttable tool

2020-08-06 Thread Huaixin Chang
Since ORC tables are already sorted by sorttable tool, let us move
building of fast lookup table into sorttable tool too. This saves us
6380us from boot time under Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz
with 64 cores.

Signed-off-by: Huaixin Chang 
Signed-off-by: Shile Zhang 
---
 arch/x86/include/asm/orc_lookup.h  | 16 --
 arch/x86/include/asm/orc_types.h   | 16 ++
 arch/x86/kernel/vmlinux.lds.S  |  2 +-
 scripts/sorttable.h| 96 +++---
 tools/arch/x86/include/asm/orc_types.h | 16 ++
 5 files changed, 122 insertions(+), 24 deletions(-)

diff --git a/arch/x86/include/asm/orc_lookup.h 
b/arch/x86/include/asm/orc_lookup.h
index 241631282e43..c75eb1f82bdb 100644
--- a/arch/x86/include/asm/orc_lookup.h
+++ b/arch/x86/include/asm/orc_lookup.h
@@ -5,22 +5,6 @@
 #ifndef _ORC_LOOKUP_H
 #define _ORC_LOOKUP_H
 
-/*
- * This is a lookup table for speeding up access to the .orc_unwind table.
- * Given an input address offset, the corresponding lookup table entry
- * specifies a subset of the .orc_unwind table to search.
- *
- * Each block represents the end of the previous range and the start of the
- * next range.  An extra block is added to give the last range an end.
- *
- * The block size should be a power of 2 to avoid a costly 'div' instruction.
- *
- * A block size of 256 was chosen because it roughly doubles unwinder
- * performance while only adding ~5% to the ORC data footprint.
- */
-#define LOOKUP_BLOCK_ORDER 8
-#define LOOKUP_BLOCK_SIZE  (1 << LOOKUP_BLOCK_ORDER)
-
 #ifndef LINKER_SCRIPT
 
 extern unsigned int orc_lookup[];
diff --git a/arch/x86/include/asm/orc_types.h b/arch/x86/include/asm/orc_types.h
index d25534940bde..b93c6a7b4da4 100644
--- a/arch/x86/include/asm/orc_types.h
+++ b/arch/x86/include/asm/orc_types.h
@@ -9,6 +9,22 @@
 #include 
 #include 
 
+/*
+ * This is a lookup table for speeding up access to the .orc_unwind table.
+ * Given an input address offset, the corresponding lookup table entry
+ * specifies a subset of the .orc_unwind table to search.
+ *
+ * Each block represents the end of the previous range and the start of the
+ * next range.  An extra block is added to give the last range an end.
+ *
+ * The block size should be a power of 2 to avoid a costly 'div' instruction.
+ *
+ * A block size of 256 was chosen because it roughly doubles unwinder
+ * performance while only adding ~5% to the ORC data footprint.
+ */
+#define LOOKUP_BLOCK_ORDER 8
+#define LOOKUP_BLOCK_SIZE  (1 << LOOKUP_BLOCK_ORDER)
+
 /*
  * The ORC_REG_* registers are base registers which are used to find other
  * registers on the stack.
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 9a03e5b23135..75760e7f6319 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -29,7 +29,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index a2baa2fefb13..de9822f8ae8f 100644
--- a/scripts/sorttable.h
+++ b/scripts/sorttable.h
@@ -93,12 +93,50 @@
 char g_err[ERRSTR_MAXSZ];
 int *g_orc_ip_table;
 struct orc_entry *g_orc_table;
+static unsigned long orc_ip_table_offset;
 
 pthread_t orc_sort_thread;
 
+struct orc_sort_param {
+   size_t  lookup_table_size;
+   unsigned int*orc_lookup_table;
+   unsigned long   start_ip;
+   size_t  text_size;
+   unsigned intorc_num_entries;
+};
+
 static inline unsigned long orc_ip(const int *ip)
 {
-   return (unsigned long)ip + *ip;
+   return (unsigned long)ip + *ip + orc_ip_table_offset;
+}
+
+static struct orc_entry *__orc_find(int *ip_table, struct orc_entry *u_table,
+   unsigned int num_entries, unsigned long ip)
+{
+   int *first = ip_table;
+   int *last = ip_table + num_entries - 1;
+   int *mid = first, *found = first;
+
+   if (!num_entries)
+   return NULL;
+
+   /*
+* Do a binary range search to find the rightmost duplicate of a given
+* starting address.  Some entries are section terminators which are
+* "weak" entries for ensuring there are no gaps.  They should be
+* ignored when they conflict with a real entry.
+*/
+   while (first <= last) {
+   mid = first + ((last - first) / 2);
+
+   if (orc_ip(mid) <= ip) {
+   found = mid;
+   first = mid + 1;
+   } else
+   last = mid - 1;
+   }
+
+   return u_table + (found - ip_table);
 }
 
 static int orc_sort_cmp(const void *_a, const void *_b)
@@ -130,18 +168,24 @@ static void *sort_orctable(void *arg)
int *idxs = NULL;
int *tmp_orc_ip_table = NULL;
struct orc_entry *tmp_orc_table = NULL;
-   unsigned int *orc_ip_size = (unsigned int *)arg;
-   unsigned int num_entries = *orc_ip_size / sizeof(int);
+ 

Re: [PATCH 2/3] scripts/sorttable: Build orc fast lookup table via sorttable tool

2020-07-26 Thread changhuaixin



> On Jul 24, 2020, at 9:53 PM, Ingo Molnar  wrote:
> 
> 
> * Huaixin Chang  wrote:
> 
>> Since orc tables are already sorted by sorttable tool, let us move
>> building of fast lookup table into sorttable tool too. This saves us
>> 6380us from boot time under Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz
>> with 64 cores.
> 
> Neat!
> 
>> +struct orc_sort_param {
>> +size_t  lookup_table_size;
>> +unsigned int*orc_lookup_table;
>> +unsigned long   start_ip;
>> +size_t  text_size;
>> +unsigned intorc_num_entries;
>> +};
> 
>> 
>> +#define LOOKUP_BLOCK_ORDER  8
>> +#define LOOKUP_BLOCK_SIZE   (1 << LOOKUP_BLOCK_ORDER)
>> +
>> +for (i = 0; i < lookup_num_blocks-1; i++) {
>> +orc = __orc_find(g_orc_ip_table, g_orc_table,
>> + num_entries,
>> + lookup_start_ip + (LOOKUP_BLOCK_SIZE * i));
>> +if (!orc) {
>> +snprintf(g_err, ERRSTR_MAXSZ,
>> +"Corrupt .orc_unwind table\n");
>> +pthread_exit(g_err);
>> +}
>> +
>> +orc_lookup[i] = orc - g_orc_table;
>> +}
>> +
>> +/* Initialize the ending block: */
>> +orc = __orc_find(g_orc_ip_table, g_orc_table, num_entries,
>> + lookup_stop_ip);
>> +if (!orc) {
>> +snprintf(g_err, ERRSTR_MAXSZ, "Corrupt .orc_unwind table\n");
>> +pthread_exit(g_err);
>> +}
>> +orc_lookup[lookup_num_blocks-1] = orc - g_orc_table;
> 
> Yeah, so now this definition of LOOKUP_BLOCK_* basicaly duplicates the 
> arch/x86/include/asm/orc_lookup.h size, with no obvious link between 
> the two. This is asking for trouble.
> 
>  looks simple enough - can we include it in 
> scripts/sorttable.h?
> 
> Or better yet, please move these two defines into , 
> which is already included in sorttable.h.
> 
Thanks!
Moving these two into  and capitalized spelling will be done 
in the following patches.

Huaixin

> BTW., please update your patches to spell 'ORC' in a capitalized 
> fashion, like most of the existing code does:
> 
>>  /* create thread to sort ORC unwind tables concurrently */
> 
> Thanks,
> 
>   Ingo



Re: [PATCH 2/3] scripts/sorttable: Build orc fast lookup table via sorttable tool

2020-07-24 Thread Ingo Molnar


* Huaixin Chang  wrote:

> Since orc tables are already sorted by sorttable tool, let us move
> building of fast lookup table into sorttable tool too. This saves us
> 6380us from boot time under Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz
> with 64 cores.

Neat!

> +struct orc_sort_param {
> + size_t  lookup_table_size;
> + unsigned int*orc_lookup_table;
> + unsigned long   start_ip;
> + size_t  text_size;
> + unsigned intorc_num_entries;
> +};

>  
> +#define LOOKUP_BLOCK_ORDER   8
> +#define LOOKUP_BLOCK_SIZE(1 << LOOKUP_BLOCK_ORDER)
> +
> + for (i = 0; i < lookup_num_blocks-1; i++) {
> + orc = __orc_find(g_orc_ip_table, g_orc_table,
> +  num_entries,
> +  lookup_start_ip + (LOOKUP_BLOCK_SIZE * i));
> + if (!orc) {
> + snprintf(g_err, ERRSTR_MAXSZ,
> + "Corrupt .orc_unwind table\n");
> + pthread_exit(g_err);
> + }
> +
> + orc_lookup[i] = orc - g_orc_table;
> + }
> +
> + /* Initialize the ending block: */
> + orc = __orc_find(g_orc_ip_table, g_orc_table, num_entries,
> +  lookup_stop_ip);
> + if (!orc) {
> + snprintf(g_err, ERRSTR_MAXSZ, "Corrupt .orc_unwind table\n");
> + pthread_exit(g_err);
> + }
> + orc_lookup[lookup_num_blocks-1] = orc - g_orc_table;

Yeah, so now this definition of LOOKUP_BLOCK_* basicaly duplicates the 
arch/x86/include/asm/orc_lookup.h size, with no obvious link between 
the two. This is asking for trouble.

 looks simple enough - can we include it in 
scripts/sorttable.h?

Or better yet, please move these two defines into , 
which is already included in sorttable.h.

BTW., please update your patches to spell 'ORC' in a capitalized 
fashion, like most of the existing code does:

>   /* create thread to sort ORC unwind tables concurrently */

Thanks,

Ingo


[PATCH 2/3] scripts/sorttable: Build orc fast lookup table via sorttable tool

2020-07-22 Thread Huaixin Chang
Since orc tables are already sorted by sorttable tool, let us move
building of fast lookup table into sorttable tool too. This saves us
6380us from boot time under Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz
with 64 cores.

Signed-off-by: Huaixin Chang 
Signed-off-by: Shile Zhang 
---
 scripts/sorttable.h | 99 +
 1 file changed, 92 insertions(+), 7 deletions(-)

diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index a2baa2fefb13..a36c76c17be4 100644
--- a/scripts/sorttable.h
+++ b/scripts/sorttable.h
@@ -93,12 +93,50 @@
 char g_err[ERRSTR_MAXSZ];
 int *g_orc_ip_table;
 struct orc_entry *g_orc_table;
+static unsigned long orc_ip_table_offset;
 
 pthread_t orc_sort_thread;
 
+struct orc_sort_param {
+   size_t  lookup_table_size;
+   unsigned int*orc_lookup_table;
+   unsigned long   start_ip;
+   size_t  text_size;
+   unsigned intorc_num_entries;
+};
+
 static inline unsigned long orc_ip(const int *ip)
 {
-   return (unsigned long)ip + *ip;
+   return (unsigned long)ip + *ip + orc_ip_table_offset;
+}
+
+static struct orc_entry *__orc_find(int *ip_table, struct orc_entry *u_table,
+   unsigned int num_entries, unsigned long ip)
+{
+   int *first = ip_table;
+   int *last = ip_table + num_entries - 1;
+   int *mid = first, *found = first;
+
+   if (!num_entries)
+   return NULL;
+
+   /*
+* Do a binary range search to find the rightmost duplicate of a given
+* starting address.  Some entries are section terminators which are
+* "weak" entries for ensuring there are no gaps.  They should be
+* ignored when they conflict with a real entry.
+*/
+   while (first <= last) {
+   mid = first + ((last - first) / 2);
+
+   if (orc_ip(mid) <= ip) {
+   found = mid;
+   first = mid + 1;
+   } else
+   last = mid - 1;
+   }
+
+   return u_table + (found - ip_table);
 }
 
 static int orc_sort_cmp(const void *_a, const void *_b)
@@ -130,18 +168,24 @@ static void *sort_orctable(void *arg)
int *idxs = NULL;
int *tmp_orc_ip_table = NULL;
struct orc_entry *tmp_orc_table = NULL;
-   unsigned int *orc_ip_size = (unsigned int *)arg;
-   unsigned int num_entries = *orc_ip_size / sizeof(int);
+   struct orc_sort_param *param = (struct orc_sort_param *)arg;
+   unsigned int num_entries = param->orc_num_entries;
+   unsigned int orc_ip_size = num_entries * sizeof(int);
unsigned int orc_size = num_entries * sizeof(struct orc_entry);
+   unsigned int lookup_num_blocks = param->lookup_table_size / sizeof(int);
+   unsigned int *orc_lookup = param->orc_lookup_table;
+   unsigned long lookup_start_ip = param->start_ip;
+   unsigned long lookup_stop_ip = param->start_ip + param->text_size;
+   struct orc_entry *orc;
 
-   idxs = (int *)malloc(*orc_ip_size);
+   idxs = (int *)malloc(orc_ip_size);
if (!idxs) {
snprintf(g_err, ERRSTR_MAXSZ, "malloc idxs: %s",
 strerror(errno));
pthread_exit(g_err);
}
 
-   tmp_orc_ip_table = (int *)malloc(*orc_ip_size);
+   tmp_orc_ip_table = (int *)malloc(orc_ip_size);
if (!tmp_orc_ip_table) {
snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_ip_table: %s",
 strerror(errno));
@@ -173,6 +217,31 @@ static void *sort_orctable(void *arg)
g_orc_table[i] = tmp_orc_table[idxs[i]];
}
 
+#define LOOKUP_BLOCK_ORDER 8
+#define LOOKUP_BLOCK_SIZE  (1 << LOOKUP_BLOCK_ORDER)
+
+   for (i = 0; i < lookup_num_blocks-1; i++) {
+   orc = __orc_find(g_orc_ip_table, g_orc_table,
+num_entries,
+lookup_start_ip + (LOOKUP_BLOCK_SIZE * i));
+   if (!orc) {
+   snprintf(g_err, ERRSTR_MAXSZ,
+   "Corrupt .orc_unwind table\n");
+   pthread_exit(g_err);
+   }
+
+   orc_lookup[i] = orc - g_orc_table;
+   }
+
+   /* Initialize the ending block: */
+   orc = __orc_find(g_orc_ip_table, g_orc_table, num_entries,
+lookup_stop_ip);
+   if (!orc) {
+   snprintf(g_err, ERRSTR_MAXSZ, "Corrupt .orc_unwind table\n");
+   pthread_exit(g_err);
+   }
+   orc_lookup[lookup_num_blocks-1] = orc - g_orc_table;
+
free(idxs);
free(tmp_orc_ip_table);
free(tmp_orc_table);
@@ -221,6 +290,8 @@ static int do_sort(Elf_Ehdr *ehdr,
unsigned int orc_ip_size = 0;
unsigned int orc_size = 0;
unsigned int orc_num_entries = 0;
+   unsigned long orc_ip_addr = 0;
+   struct orc_sort_param param;
 #endif
 
   

[PATCH 2/3] scripts/sorttable: Build orc fast lookup table via sorttable tool

2020-06-03 Thread Huaixin Chang
Since orc tables are already sorted by sorttable tool, let us move
building of fast lookup table into sorttable tool too. This saves us
6380us from boot time under Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz
with 64 cores.

Signed-off-by: Huaixin Chang 
Signed-off-by: Shile Zhang 
---
 scripts/sorttable.h | 99 +
 1 file changed, 92 insertions(+), 7 deletions(-)

diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index a2baa2fefb13..a36c76c17be4 100644
--- a/scripts/sorttable.h
+++ b/scripts/sorttable.h
@@ -93,12 +93,50 @@
 char g_err[ERRSTR_MAXSZ];
 int *g_orc_ip_table;
 struct orc_entry *g_orc_table;
+static unsigned long orc_ip_table_offset;
 
 pthread_t orc_sort_thread;
 
+struct orc_sort_param {
+   size_t  lookup_table_size;
+   unsigned int*orc_lookup_table;
+   unsigned long   start_ip;
+   size_t  text_size;
+   unsigned intorc_num_entries;
+};
+
 static inline unsigned long orc_ip(const int *ip)
 {
-   return (unsigned long)ip + *ip;
+   return (unsigned long)ip + *ip + orc_ip_table_offset;
+}
+
+static struct orc_entry *__orc_find(int *ip_table, struct orc_entry *u_table,
+   unsigned int num_entries, unsigned long ip)
+{
+   int *first = ip_table;
+   int *last = ip_table + num_entries - 1;
+   int *mid = first, *found = first;
+
+   if (!num_entries)
+   return NULL;
+
+   /*
+* Do a binary range search to find the rightmost duplicate of a given
+* starting address.  Some entries are section terminators which are
+* "weak" entries for ensuring there are no gaps.  They should be
+* ignored when they conflict with a real entry.
+*/
+   while (first <= last) {
+   mid = first + ((last - first) / 2);
+
+   if (orc_ip(mid) <= ip) {
+   found = mid;
+   first = mid + 1;
+   } else
+   last = mid - 1;
+   }
+
+   return u_table + (found - ip_table);
 }
 
 static int orc_sort_cmp(const void *_a, const void *_b)
@@ -130,18 +168,24 @@ static void *sort_orctable(void *arg)
int *idxs = NULL;
int *tmp_orc_ip_table = NULL;
struct orc_entry *tmp_orc_table = NULL;
-   unsigned int *orc_ip_size = (unsigned int *)arg;
-   unsigned int num_entries = *orc_ip_size / sizeof(int);
+   struct orc_sort_param *param = (struct orc_sort_param *)arg;
+   unsigned int num_entries = param->orc_num_entries;
+   unsigned int orc_ip_size = num_entries * sizeof(int);
unsigned int orc_size = num_entries * sizeof(struct orc_entry);
+   unsigned int lookup_num_blocks = param->lookup_table_size / sizeof(int);
+   unsigned int *orc_lookup = param->orc_lookup_table;
+   unsigned long lookup_start_ip = param->start_ip;
+   unsigned long lookup_stop_ip = param->start_ip + param->text_size;
+   struct orc_entry *orc;
 
-   idxs = (int *)malloc(*orc_ip_size);
+   idxs = (int *)malloc(orc_ip_size);
if (!idxs) {
snprintf(g_err, ERRSTR_MAXSZ, "malloc idxs: %s",
 strerror(errno));
pthread_exit(g_err);
}
 
-   tmp_orc_ip_table = (int *)malloc(*orc_ip_size);
+   tmp_orc_ip_table = (int *)malloc(orc_ip_size);
if (!tmp_orc_ip_table) {
snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_ip_table: %s",
 strerror(errno));
@@ -173,6 +217,31 @@ static void *sort_orctable(void *arg)
g_orc_table[i] = tmp_orc_table[idxs[i]];
}
 
+#define LOOKUP_BLOCK_ORDER 8
+#define LOOKUP_BLOCK_SIZE  (1 << LOOKUP_BLOCK_ORDER)
+
+   for (i = 0; i < lookup_num_blocks-1; i++) {
+   orc = __orc_find(g_orc_ip_table, g_orc_table,
+num_entries,
+lookup_start_ip + (LOOKUP_BLOCK_SIZE * i));
+   if (!orc) {
+   snprintf(g_err, ERRSTR_MAXSZ,
+   "Corrupt .orc_unwind table\n");
+   pthread_exit(g_err);
+   }
+
+   orc_lookup[i] = orc - g_orc_table;
+   }
+
+   /* Initialize the ending block: */
+   orc = __orc_find(g_orc_ip_table, g_orc_table, num_entries,
+lookup_stop_ip);
+   if (!orc) {
+   snprintf(g_err, ERRSTR_MAXSZ, "Corrupt .orc_unwind table\n");
+   pthread_exit(g_err);
+   }
+   orc_lookup[lookup_num_blocks-1] = orc - g_orc_table;
+
free(idxs);
free(tmp_orc_ip_table);
free(tmp_orc_table);
@@ -221,6 +290,8 @@ static int do_sort(Elf_Ehdr *ehdr,
unsigned int orc_ip_size = 0;
unsigned int orc_size = 0;
unsigned int orc_num_entries = 0;
+   unsigned long orc_ip_addr = 0;
+   struct orc_sort_param param;
 #endif
 
   

[PATCH 2/3] scripts/sorttable: Build orc fast lookup table via sorttable tool

2020-06-03 Thread Huaixin Chang
Since orc tables are already sorted by sorttable tool, let us move
building of fast lookup table into sorttable tool too. This saves us
6380us from boot time under Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz
with 64 cores.

Signed-off-by: Huaixin Chang 
Signed-off-by: Shile Zhang 
---
 scripts/sorttable.h | 99 +
 1 file changed, 92 insertions(+), 7 deletions(-)

diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index a2baa2fefb13..a36c76c17be4 100644
--- a/scripts/sorttable.h
+++ b/scripts/sorttable.h
@@ -93,12 +93,50 @@
 char g_err[ERRSTR_MAXSZ];
 int *g_orc_ip_table;
 struct orc_entry *g_orc_table;
+static unsigned long orc_ip_table_offset;
 
 pthread_t orc_sort_thread;
 
+struct orc_sort_param {
+   size_t  lookup_table_size;
+   unsigned int*orc_lookup_table;
+   unsigned long   start_ip;
+   size_t  text_size;
+   unsigned intorc_num_entries;
+};
+
 static inline unsigned long orc_ip(const int *ip)
 {
-   return (unsigned long)ip + *ip;
+   return (unsigned long)ip + *ip + orc_ip_table_offset;
+}
+
+static struct orc_entry *__orc_find(int *ip_table, struct orc_entry *u_table,
+   unsigned int num_entries, unsigned long ip)
+{
+   int *first = ip_table;
+   int *last = ip_table + num_entries - 1;
+   int *mid = first, *found = first;
+
+   if (!num_entries)
+   return NULL;
+
+   /*
+* Do a binary range search to find the rightmost duplicate of a given
+* starting address.  Some entries are section terminators which are
+* "weak" entries for ensuring there are no gaps.  They should be
+* ignored when they conflict with a real entry.
+*/
+   while (first <= last) {
+   mid = first + ((last - first) / 2);
+
+   if (orc_ip(mid) <= ip) {
+   found = mid;
+   first = mid + 1;
+   } else
+   last = mid - 1;
+   }
+
+   return u_table + (found - ip_table);
 }
 
 static int orc_sort_cmp(const void *_a, const void *_b)
@@ -130,18 +168,24 @@ static void *sort_orctable(void *arg)
int *idxs = NULL;
int *tmp_orc_ip_table = NULL;
struct orc_entry *tmp_orc_table = NULL;
-   unsigned int *orc_ip_size = (unsigned int *)arg;
-   unsigned int num_entries = *orc_ip_size / sizeof(int);
+   struct orc_sort_param *param = (struct orc_sort_param *)arg;
+   unsigned int num_entries = param->orc_num_entries;
+   unsigned int orc_ip_size = num_entries * sizeof(int);
unsigned int orc_size = num_entries * sizeof(struct orc_entry);
+   unsigned int lookup_num_blocks = param->lookup_table_size / sizeof(int);
+   unsigned int *orc_lookup = param->orc_lookup_table;
+   unsigned long lookup_start_ip = param->start_ip;
+   unsigned long lookup_stop_ip = param->start_ip + param->text_size;
+   struct orc_entry *orc;
 
-   idxs = (int *)malloc(*orc_ip_size);
+   idxs = (int *)malloc(orc_ip_size);
if (!idxs) {
snprintf(g_err, ERRSTR_MAXSZ, "malloc idxs: %s",
 strerror(errno));
pthread_exit(g_err);
}
 
-   tmp_orc_ip_table = (int *)malloc(*orc_ip_size);
+   tmp_orc_ip_table = (int *)malloc(orc_ip_size);
if (!tmp_orc_ip_table) {
snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_ip_table: %s",
 strerror(errno));
@@ -173,6 +217,31 @@ static void *sort_orctable(void *arg)
g_orc_table[i] = tmp_orc_table[idxs[i]];
}
 
+#define LOOKUP_BLOCK_ORDER 8
+#define LOOKUP_BLOCK_SIZE  (1 << LOOKUP_BLOCK_ORDER)
+
+   for (i = 0; i < lookup_num_blocks-1; i++) {
+   orc = __orc_find(g_orc_ip_table, g_orc_table,
+num_entries,
+lookup_start_ip + (LOOKUP_BLOCK_SIZE * i));
+   if (!orc) {
+   snprintf(g_err, ERRSTR_MAXSZ,
+   "Corrupt .orc_unwind table\n");
+   pthread_exit(g_err);
+   }
+
+   orc_lookup[i] = orc - g_orc_table;
+   }
+
+   /* Initialize the ending block: */
+   orc = __orc_find(g_orc_ip_table, g_orc_table, num_entries,
+lookup_stop_ip);
+   if (!orc) {
+   snprintf(g_err, ERRSTR_MAXSZ, "Corrupt .orc_unwind table\n");
+   pthread_exit(g_err);
+   }
+   orc_lookup[lookup_num_blocks-1] = orc - g_orc_table;
+
free(idxs);
free(tmp_orc_ip_table);
free(tmp_orc_table);
@@ -221,6 +290,8 @@ static int do_sort(Elf_Ehdr *ehdr,
unsigned int orc_ip_size = 0;
unsigned int orc_size = 0;
unsigned int orc_num_entries = 0;
+   unsigned long orc_ip_addr = 0;
+   struct orc_sort_param param;
 #endif