--- /dev/null
+#ifndef _SDT_H_
+#define _SDT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(CONFIG_DTRACE) || defined(CONFIG_DTRACE_MODULE)
+
+#ifndef __KERNEL__
+
+#define DTRACE_PROBE(provider, name) { \
+ extern void __dtrace_##provider##___##name(void); \
+ __dtrace_##provider##___##name(); \
+}
+
+#define DTRACE_PROBE1(provider, name, arg1) { \
+ extern void __dtrace_##provider##___##name(unsigned long); \
+ __dtrace_##provider##___##name((unsigned long)arg1); \
+}
+
+#define DTRACE_PROBE2(provider, name, arg1, arg2) { \
+ extern void __dtrace_##provider##___##name(unsigned long, \
+ unsigned long); \
+ __dtrace_##provider##___##name((unsigned long)arg1, \
+ (unsigned long)arg2); \
+}
+
+#define DTRACE_PROBE3(provider, name, arg1, arg2, arg3) { \
+ extern void __dtrace_##provider##___##name(unsigned long, \
+ unsigned long, unsigned long); \
+ __dtrace_##provider##___##name((unsigned long)arg1, \
+ (unsigned long)arg2, (unsigned long)arg3); \
+}
+
+#define DTRACE_PROBE4(provider, name, arg1, arg2, arg3, arg4) { \
+ extern void __dtrace_##provider##___##name(unsigned long, \
+ unsigned long, unsigned long, unsigned long); \
+ __dtrace_##provider##___##name((unsigned long)arg1, \
+ (unsigned long)arg2, (unsigned long)arg3, \
+ (unsigned long)arg4); \
+}
+
+#define DTRACE_PROBE5(provider, name, arg1, arg2, arg3, arg4, arg5) { \
+ extern void __dtrace_##provider##___##name(unsigned long, \
+ unsigned long, unsigned long, unsigned long, unsigned long);\
+ __dtrace_##provider##___##name((unsigned long)arg1, \
+ (unsigned long)arg2, (unsigned long)arg3, \
+ (unsigned long)arg4, (unsigned long)arg5); \
+}
+
+#else /* __KERNEL__ */
+
+#define DTRACE_PROBE(name) { \
+ extern void __dtrace_probe_##name(void); \
+ __dtrace_probe_##name(); \
+}
+
+#define DTRACE_PROBE1(name, type1, arg1) { \
+ extern void __dtrace_probe_##name(uintptr_t); \
+ __dtrace_probe_##name((uintptr_t)(arg1)); \
+}
+
+#define DTRACE_PROBE2(name, type1, arg1, type2, arg2) { \
+ extern void __dtrace_probe_##name(uintptr_t, uintptr_t); \
+ __dtrace_probe_##name((uintptr_t)(arg1), (uintptr_t)(arg2)); \
+}
+
+#define DTRACE_PROBE3(name, type1, arg1, type2, arg2, type3, arg3) { \
+ extern void __dtrace_probe_##name(uintptr_t, uintptr_t, uintptr_t); \
+ __dtrace_probe_##name((uintptr_t)(arg1), (uintptr_t)(arg2), \
+ (uintptr_t)(arg3)); \
+}
+
+#define DTRACE_PROBE4(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4) { \
+ extern void __dtrace_probe_##name(uintptr_t, uintptr_t, \
+ uintptr_t, uintptr_t); \
+ __dtrace_probe_##name((uintptr_t)(arg1), (uintptr_t)(arg2), \
+ (uintptr_t)(arg3), (uintptr_t)(arg4)); \
+}
+
+#define DTRACE_PROBE5(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5) { \
+ extern void __dtrace_probe_##name(uintptr_t, uintptr_t, \
+ uintptr_t, uintptr_t, uintptr_t); \
+ __dtrace_probe_##name((uintptr_t)(arg1), (uintptr_t)(arg2), \
+ (uintptr_t)(arg3), (uintptr_t)(arg4), (uintptr_t)(arg5)); \
+}
+
+#define DTRACE_PROBE6(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6) { \
+ extern void __dtrace_probe_##name(uintptr_t, uintptr_t, \
+ uintptr_t, uintptr_t, uintptr_t, uintptr_t); \
+ __dtrace_probe_##name((uintptr_t)(arg1), (uintptr_t)(arg2), \
+ (uintptr_t)(arg3), (uintptr_t)(arg4), (uintptr_t)(arg5), \
+ (uintptr_t)(arg6)); \
+}
+
+#define DTRACE_PROBE7(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6, type7, arg7) { \
+ extern void __dtrace_probe_##name(uintptr_t, uintptr_t, \
+ uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); \
+ __dtrace_probe_##name((uintptr_t)(arg1), (uintptr_t)(arg2), \
+ (uintptr_t)(arg3), (uintptr_t)(arg4), (uintptr_t)(arg5), \
+ (uintptr_t)(arg6), (uintptr_t)(arg7)); \
+}
+
+#define DTRACE_PROBE8(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8) { \
+ extern void __dtrace_probe_##name(uintptr_t, uintptr_t, \
+ uintptr_t, uintptr_t, uintptr_t, uintptr_t, \
+ uintptr_t, uintptr_t); \
+ __dtrace_probe_##name((uintptr_t)(arg1), (uintptr_t)(arg2), \
+ (uintptr_t)(arg3), (uintptr_t)(arg4), (uintptr_t)(arg5), \
+ (uintptr_t)(arg6), (uintptr_t)(arg7), (uintptr_t)(arg8)); \
+}
+
+/*
+ * vmlinux dtrace_probe__ caller reloc info;
+ * comes from vmlinux_info.S
+ */
+extern unsigned long dtrace_relocs_count __attribute__((weak));
+extern void *dtrace_relocs __attribute__((weak));
+
+struct reloc_info {
+ unsigned long probe_offset;
+ unsigned long section_base;
+ unsigned long probe_name_len;
+ char probe_name[0];
+} __aligned(sizeof(unsigned long));
+
+void dtrace_register_builtins(void);
+
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#endif /* __KERNEL__ */
+
+#else /* DTRACE not enabled: */
+
+#define DTRACE_PROBE(name) do { } while (0)
+#define DTRACE_PROBE1(name, type1, arg1) DTRACE_PROBE(name)
+#define DTRACE_PROBE2(name, type1, arg1, type2, arg2) DTRACE_PROBE(name)
+#define DTRACE_PROBE3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE(name)
+#define DTRACE_PROBE4(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4) DTRACE_PROBE(name)
+#define DTRACE_PROBE5(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5) DTRACE_PROBE(name)
+#define DTRACE_PROBE6(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6) DTRACE_PROBE(name)
+#define DTRACE_PROBE7(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6, type7, arg7) DTRACE_PROBE(name)
+#define DTRACE_PROBE8(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8) \
+ DTRACE_PROBE(name)
+
+#endif /* CONFIG_DTRACE */
+
+
+#define DTRACE_SCHED(name) \
+ DTRACE_PROBE(__sched_##name);
+
+#define DTRACE_SCHED1(name, type1, arg1) \
+ DTRACE_PROBE1(__sched_##name, type1, arg1);
+
+#define DTRACE_SCHED2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__sched_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_SCHED3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE3(__sched_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define DTRACE_SCHED4(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4) \
+ DTRACE_PROBE4(__sched_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4);
+
+#define DTRACE_PROC(name) \
+ DTRACE_PROBE(__proc_##name);
+
+#define DTRACE_PROC1(name, type1, arg1) \
+ DTRACE_PROBE1(__proc_##name, type1, arg1);
+
+#define DTRACE_PROC2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__proc_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_PROC3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE3(__proc_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define DTRACE_PROC4(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4) \
+ DTRACE_PROBE4(__proc_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4);
+
+#define DTRACE_IO(name) \
+ DTRACE_PROBE(__io_##name);
+
+#define DTRACE_IO1(name, type1, arg1) \
+ DTRACE_PROBE1(__io_##name, type1, arg1);
+
+#define DTRACE_IO2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__io_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_IO3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE3(__io_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define DTRACE_IO4(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4) \
+ DTRACE_PROBE4(__io_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4);
+
+#define DTRACE_ISCSI_2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__iscsi_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_ISCSI_3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE3(__iscsi_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define DTRACE_ISCSI_4(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4) \
+ DTRACE_PROBE4(__iscsi_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4);
+
+#define DTRACE_ISCSI_5(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5) \
+ DTRACE_PROBE5(__iscsi_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5);
+
+#define DTRACE_ISCSI_6(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6) \
+ DTRACE_PROBE6(__iscsi_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6);
+
+#define DTRACE_ISCSI_7(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7) \
+ DTRACE_PROBE7(__iscsi_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6, \
+ type7, arg7);
+
+#define DTRACE_ISCSI_8(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6, \
+ type7, arg7, type8, arg8) \
+ DTRACE_PROBE8(__iscsi_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6, \
+ type7, arg7, type8, arg8);
+
+#define DTRACE_NFSV3_3(name, type1, arg1, type2, arg2, \
+ type3, arg3) \
+ DTRACE_PROBE3(__nfsv3_##name, type1, arg1, type2, arg2, \
+ type3, arg3);
+#define DTRACE_NFSV3_4(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4) \
+ DTRACE_PROBE4(__nfsv3_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4);
+
+#define DTRACE_NFSV4_1(name, type1, arg1) \
+ DTRACE_PROBE1(__nfsv4_##name, type1, arg1);
+
+#define DTRACE_NFSV4_2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__nfsv4_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_NFSV4_3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE3(__nfsv4_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define DTRACE_SMB_1(name, type1, arg1) \
+ DTRACE_PROBE1(__smb_##name, type1, arg1);
+
+#define DTRACE_SMB_2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__smb_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_IP(name) \
+ DTRACE_PROBE(__ip_##name);
+
+#define DTRACE_IP1(name, type1, arg1) \
+ DTRACE_PROBE1(__ip_##name, type1, arg1);
+
+#define DTRACE_IP2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__ip_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_IP3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE3(__ip_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define DTRACE_IP4(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4) \
+ DTRACE_PROBE4(__ip_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4);
+
+#define DTRACE_IP5(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5) \
+ DTRACE_PROBE5(__ip_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5);
+
+#define DTRACE_IP6(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6) \
+ DTRACE_PROBE6(__ip_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6);
+
+#define DTRACE_IP7(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6, type7, arg7) \
+ DTRACE_PROBE7(__ip_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6, \
+ type7, arg7);
+
+#define DTRACE_TCP(name) \
+ DTRACE_PROBE(__tcp_##name);
+
+#define DTRACE_TCP1(name, type1, arg1) \
+ DTRACE_PROBE1(__tcp_##name, type1, arg1);
+
+#define DTRACE_TCP2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__tcp_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_TCP3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE3(__tcp_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define DTRACE_TCP4(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4) \
+ DTRACE_PROBE4(__tcp_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4);
+
+#define DTRACE_TCP5(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5) \
+ DTRACE_PROBE5(__tcp_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5);
+
+#define DTRACE_TCP6(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6) \
+ DTRACE_PROBE6(__tcp_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6);
+
+#define DTRACE_UDP(name) \
+ DTRACE_PROBE(__udp_##name);
+
+#define DTRACE_UDP1(name, type1, arg1) \
+ DTRACE_PROBE1(__udp_##name, type1, arg1);
+
+#define DTRACE_UDP2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__udp_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_UDP3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE3(__udp_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define DTRACE_UDP4(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4) \
+ DTRACE_PROBE4(__udp_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4);
+
+#define DTRACE_UDP5(name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5) \
+ DTRACE_PROBE5(__udp_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5);
+
+
+#define DTRACE_SYSEVENT2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__sysevent_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_XPV(name) \
+ DTRACE_PROBE(__xpv_##name);
+
+#define DTRACE_XPV1(name, type1, arg1) \
+ DTRACE_PROBE1(__xpv_##name, type1, arg1);
+
+#define DTRACE_XPV2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__xpv_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_XPV3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE3(__xpv_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define DTRACE_XPV4(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4) \
+ DTRACE_PROBE4(__xpv_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4);
+
+#define DTRACE_FC_1(name, type1, arg1) \
+ DTRACE_PROBE1(__fc_##name, type1, arg1);
+
+#define DTRACE_FC_2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__fc_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_FC_3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE3(__fc_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define DTRACE_FC_4(name, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \
+ DTRACE_PROBE4(__fc_##name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4);
+
+#define DTRACE_FC_5(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5) \
+ DTRACE_PROBE5(__fc_##name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5);
+
+#define DTRACE_SRP_1(name, type1, arg1) \
+ DTRACE_PROBE1(__srp_##name, type1, arg1);
+
+#define DTRACE_SRP_2(name, type1, arg1, type2, arg2) \
+ DTRACE_PROBE2(__srp_##name, type1, arg1, type2, arg2);
+
+#define DTRACE_SRP_3(name, type1, arg1, type2, arg2, type3, arg3) \
+ DTRACE_PROBE3(__srp_##name, type1, arg1, type2, arg2, type3, arg3);
+
+#define DTRACE_SRP_4(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4) \
+ DTRACE_PROBE4(__srp_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4);
+
+#define DTRACE_SRP_5(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5) \
+ DTRACE_PROBE5(__srp_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5);
+
+#define DTRACE_SRP_6(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6) \
+ DTRACE_PROBE6(__srp_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6);
+
+#define DTRACE_SRP_7(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6, type7, arg7) \
+ DTRACE_PROBE7(__srp_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6, type7, arg7);
+
+#define DTRACE_SRP_8(name, type1, arg1, type2, arg2, type3, arg3, \
+ type4, arg4, type5, arg5, type6, arg6, type7, arg7, type8, arg8) \
+ DTRACE_PROBE8(__srp_##name, type1, arg1, type2, arg2, \
+ type3, arg3, type4, arg4, type5, arg5, type6, arg6, \
+ type7, arg7, type8, arg8);
+
+extern const char *sdt_prefix;
+
+typedef struct sdt_probedesc {
+ char *sdpd_name; /* name of this probe */
+ unsigned long sdpd_offset; /* offset of call in text */
+ struct sdt_probedesc *sdpd_next; /* next static probe */
+} sdt_probedesc_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SDT_H_ */
--- /dev/null
+/* Generate assembler source containing __dtrace_probe_* calls (reloc info)
+ *
+ * Based on scripts/kallsyms.c
+ * Copyright 2002 by Kai Germaschewski
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * Usage: dtrace_relocs input_file_text output_file_elf
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <ctype.h>
+#include <elf.h>
+
+struct sym_entry {
+ unsigned long long addr;
+ unsigned char is_section;
+ unsigned char section_used;
+ int section_index;
+ unsigned long long section_base;
+ unsigned int len;
+ char *sym;
+};
+
+struct text_range {
+ const char *stext, *etext;
+ unsigned long long start, end;
+};
+
+static unsigned long long _text; // TBD: need this from System.map
+
+static struct sym_entry *table;
+static unsigned int table_size, table_cnt;
+static int this_section_index;
+static unsigned long long this_section_addr;
+static int relocs_count;
+
+static void usage(void)
+{
+ fprintf(stderr, "Usage: dtrace_relocs input_file_text output_file_elf\n");
+ exit(1);
+}
+
+// skip over whitespace (spaces or tabs)
+static char *deblank(char *str)
+{
+ while (*str == ' ' || *str == '\t')
+ str++;
+ return str;
+}
+
+static int find_section(char *sect, int sectlen)
+{
+ int ix;
+ struct sym_entry *sym = table;
+
+#if 0
+ fprintf(stderr, "%s: search for sect=<%s>, sectlen=%d:\n",
+ __func__, sect, sectlen);
+#endif
+
+ for (ix = 0; ix < table_cnt; ix++, sym++) {
+#if 0
+ if (sym->is_section && strlen(sym->sym) == sectlen)
+ fprintf(stderr, "%s: ix=%d, symlen=%d, symname=<%s>\n",
+ __func__, ix, strlen(sym->sym), sym->sym);
+#endif
+ if (sym->is_section && strlen(sym->sym) == sectlen &&
+ strncmp(sym->sym, sect, sectlen) == 0) {
+ sym->section_used = true;
+ this_section_addr = sym->addr;
+ return sym->section_index;
+ }
+ }
+
+ return -1;
+}
+
+static int get_this_section(char buf[500])
+{
+ char *sect;
+ int sectlen;
+ int sect_index;
+
+ if (strncmp(buf, "RELOCATION RECORDS FOR [", 24) != 0) {
+ fprintf(stderr, "Bad relocation header: %s\n", buf);
+ exit(2);
+ }
+
+ sect = buf + 24;
+ sectlen = strlen(sect); // includes a trailing newline
+#if 0
+ fprintf(stderr, "%s: sect=<%s>, sectlen=%d\n",
+ __func__, sect, sectlen);
+#endif
+ if (*(sect + sectlen - 3) != ']' || *(sect + sectlen - 2) != ':') {
+ fprintf(stderr, "Bad relocation header: %s\n", buf);
+ exit(2);
+ }
+ *(sect + sectlen - 3) = '\0';
+ sectlen -= 3; // drop the "]:\n"
+#if 0
+ fprintf(stderr, "%s: isolated section name=<%s>\n", __func__, sect);
+#endif
+ sect_index = find_section(sect, sectlen);
+ if (sect_index < 0) {
+ fprintf(stderr, "Bad section name in relocation header: %s\n",
+ sect);
+ exit(2);
+ }
+
+ return sect_index;
+}
+
+/*
+ * scans 2 lines of section info;
+ * first line is already in buf;
+ * second line is noise for now;
+ */
+static int get_section_info(FILE *fin, char buf[500], struct sym_entry *sect)
+{
+ int rc;
+ int sect_index;
+ char sect_name[200], sect_align[100];
+ unsigned long sect_size, file_offset;
+ unsigned long long vma, lma;
+ char sect_flags[500];
+ char *flags;
+
+ rc = sscanf(buf, " %d %s %lx %llx %llx %lx %s \n",
+ §_index, (char *)§_name, §_size, &vma, &lma,
+ &file_offset, (char *)§_align);
+#ifdef SCANF
+ fprintf(stderr, "%s: sscanf.1 rc= %d\n", __func__, rc);
+#endif
+ if (rc != 7)
+ return -1;
+
+ if (!fgets(sect_flags, sizeof(sect_flags), fin))
+ return -1;
+
+#ifdef SCANF
+ fprintf(stderr, "%s: fgets.2 read=<%s>", __func__, sect_flags);
+#endif
+ flags = deblank(sect_flags);
+
+ sect->addr = file_offset;
+ sect->is_section = true;
+ sect->section_used = false;
+ sect->section_index = sect_index;
+ sect->len = sect_size;
+ sect->sym = malloc(strlen(sect_name));
+ if (!sect->sym) {
+ fprintf(stderr, "relocs failure: "
+ "unable to allocate required amount of memory\n");
+ exit(1);
+ }
+ strcpy((char *)sect->sym, sect_name);
+
+#ifdef INFO
+ fprintf(stderr, "sect: index=%d, name=%s, addr/offset=0x%llx, sect_size=0x%x, align=%s, vma=0x%llx, lma=0x%llx, flags=%s\n",
+ sect_index, sect->sym, sect->addr, sect->len, sect_align,
+ vma, lma, flags);
+#endif
+
+ return 0;
+}
+
+static int get_symbol_info(char buf[500], struct sym_entry *s)
+{
+ int rc;
+ unsigned long long relo_offset, pp_offset;
+ char relo_type[200];
+ char probepoint[200];
+
+ //rc = sscanf(buf, " %llx %s %200s-%llx \n",
+ rc = sscanf(buf, " %llx %s %[^ -]-%llx \n",
+ &relo_offset, (char *)&relo_type,
+ (char *)&probepoint, &pp_offset);
+#ifdef SCANF
+ fprintf(stderr, "%s: sscanf.1 rc= %d\n", __func__, rc);
+#endif
+ if (rc != 4)
+ return -1;
+
+ s->addr = relo_offset;
+ s->len = strlen(probepoint);
+ s->is_section = false;
+ s->section_used = false;
+ s->section_index = -1;
+ s->section_base = this_section_addr;
+ s->sym = malloc(s->len + 1);
+ if (!s->sym) {
+ fprintf(stderr, "relocs failure: "
+ "unable to allocate required amount of memory\n");
+ exit(1);
+ }
+ strcpy((char *)s->sym, probepoint);
+
+#ifdef INFO
+ fprintf(stderr, "sym: addr/offset=0x%llx, strlen=%d, type=%s, name=%s\n",
+ s->addr, s->len, relo_type, s->sym);
+#endif
+
+ relocs_count++;
+ return 0;
+}
+
+static void read_info(FILE *fin)
+{
+ char buf[500];
+ bool in_sections = false, in_symbols = false;
+
+ while (!feof(fin)) {
+ if (table_cnt >= table_size) {
+ table_size += 10000;
+ table = realloc(table, sizeof(*table) * table_size);
+ if (!table) {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+ }
+
+ if (!fgets(buf, sizeof(buf), fin))
+ break;
+#ifdef SCANF
+ fprintf(stderr, "dtr: buf=<%s>\n", buf);
+#endif
+
+ if (strncmp(buf, "Sections:", 9) == 0) {
+ in_sections = true;
+ continue;
+ }
+ if (strncmp(buf, "RELOCATION RECORDS", 11) == 0) {
+ in_sections = false;
+ in_symbols = true;
+ // isolate & look up section name, get its index
+ // this call also sets 'this_section_addr'
+ this_section_index = get_this_section(buf);
+ continue;
+ }
+
+ if (in_sections) {
+ if (strncmp(buf, "Idx ", 4) != 0)
+ if (get_section_info(fin, buf, &table[table_cnt]) == 0)
+ table_cnt++;
+ continue;
+ }
+
+ if (in_symbols)
+ if (get_symbol_info(buf, &table[table_cnt]) == 0)
+ table_cnt++;
+ }
+}
+
+static void output_label(FILE *fout, char *label)
+{
+ fprintf(fout, ".globl %s\n", label);
+ fprintf(fout, "\tALGN\n");
+ fprintf(fout, "%s:\n", label);
+}
+
+static void write_relocs(FILE *fout)
+{
+ unsigned int i;
+ int reloc_count = 0;
+
+ fprintf(fout, "#include <asm/types.h>\n");
+ fprintf(fout, "#if BITS_PER_LONG == 64\n");
+ fprintf(fout, "#define PTR .quad\n");
+ fprintf(fout, "#define ALGN .align 8\n");
+ fprintf(fout, "#else\n");
+ fprintf(fout, "#define PTR .long\n");
+ fprintf(fout, "#define ALGN .align 4\n");
+ fprintf(fout, "#endif\n");
+
+ fprintf(fout, "\t.section .rodata, \"a\"\n");
+ fprintf(fout, "\n");
+
+ output_label(fout, "dtrace_relocs_count");
+ fprintf(fout, "\tPTR\t%d\n", relocs_count);
+ fprintf(fout, "\n");
+
+ /*
+ * Provide proper symbols relocatability by their '_text'
+ * relativeness. The symbol names cannot be used to construct
+ * normal symbol references as the list of symbols contains
+ * symbols that are declared static and are private to their
+ * .o files. This prevents .tmp_kallsyms.o or any other
+ * object from referencing them.
+ */
+ output_label(fout, "dtrace_relocs");
+ for (i = 0; i < table_cnt; i++) {
+#if 0
+ if (_text <= table[i].addr)
+ fprintf(fout, "\tPTR\t_text + %#llx\n",
+ table[i].addr - _text);
+ else
+ fprintf(fout, "\tPTR\t_text - %#llx\n",
+ _text - table[i].addr);
+#endif
+ // for reloc symbols (not sections):
+ // print symbol relative address, section base address,
+ // call target string length, call target string/name;
+ // TBD: figure out how to find the next 4-tuple;
+ if (!table[i].is_section) {
+ fprintf(fout, "\tPTR\t%#llx\n", table[i].addr);
+ fprintf(fout, "\tPTR\t%#llx\n", table[i].section_base);
+ fprintf(fout, "\tPTR\t%d\n", table[i].len);
+ fprintf(fout, "\t.asciz\t\"%s\"\n", table[i].sym);
+ fprintf(fout, "\tALGN\n");
+ reloc_count++;
+ }
+ }
+
+ fprintf(fout, "\n");
+
+ if (reloc_count != relocs_count) {
+ fprintf(fout, "relocs error: reloc counters do not agree (%d vs. %d\n)",
+ relocs_count, reloc_count);
+ exit(3);
+ }
+}
+
+#if 0
+/* guess for "linker script provide" symbol */
+static int may_be_linker_script_provide_symbol(const struct sym_entry *se)
+{
+ const char *symbol = (char *)se->sym + 1;
+ int len = se->len - 1;
+
+ if (len < 8)
+ return 0;
+
+ if (symbol[0] != '_' || symbol[1] != '_')
+ return 0;
+
+ /* __start_XXXXX */
+ if (!memcmp(symbol + 2, "start_", 6))
+ return 1;
+
+ /* __stop_XXXXX */
+ if (!memcmp(symbol + 2, "stop_", 5))
+ return 1;
+
+ /* __end_XXXXX */
+ if (!memcmp(symbol + 2, "end_", 4))
+ return 1;
+
+ /* __XXXXX_start */
+ if (!memcmp(symbol + len - 6, "_start", 6))
+ return 1;
+
+ /* __XXXXX_end */
+ if (!memcmp(symbol + len - 4, "_end", 4))
+ return 1;
+
+ return 0;
+}
+#endif
+
+int main(int argc, char *argv[])
+{
+ char *infile, *outfile;
+ FILE *fin, *fout;
+
+
+ if (argc != 3)
+ usage();
+
+ infile = argv[1];
+ outfile = argv[2];
+
+ fin = fopen(infile, "r");
+ if (!fin) {
+ fprintf(stderr, "relocs: cannot open input file '%s'\n",
+ infile);
+ exit(2);
+ }
+ fout = fopen(outfile, "w");
+ if (!fout) {
+ fprintf(stderr, "relocs: cannot create output file '%s'\n",
+ outfile);
+ exit(2);
+ }
+
+ read_info(fin);
+ fclose(fin);
+
+ write_relocs(fout);
+ fclose(fout);
+
+ return 0;
+}