Merge branches 'x86-fixes-for-linus', 'sched-fixes-for-linus', 'timers-fixes-for-linus', 'irq-fixes-for-linus' and 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86-32, fpu: Fix FPU exception handling on non-SSE systems x86, hibernate: Initialize mmu_cr4_features during boot x86-32, NUMA: Fix ACPI NUMA init broken by recent x86-64 change x86: visws: Fixup irq overhaul fallout * 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: sched: Clean up rebalance_domains() load-balance interval calculation * 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86/mrst/vrtc: Fix boot crash in mrst_rtc_init() rtc, x86/mrst/vrtc: Fix boot crash in rtc_read_alarm() * 'irq-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: genirq: Fix cpumask leak in __setup_irq() * 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: perf probe: Fix listing incorrect line number with inline function perf probe: Fix to find recursively inlined function perf probe: Fix multiple --vars options behavior perf probe: Fix to remove redundant close perf probe: Fix to ensure function declared file
This commit is contained in:
@@ -237,7 +237,7 @@ static inline void fpu_save_init(struct fpu *fpu)
|
|||||||
} else if (use_fxsr()) {
|
} else if (use_fxsr()) {
|
||||||
fpu_fxsave(fpu);
|
fpu_fxsave(fpu);
|
||||||
} else {
|
} else {
|
||||||
asm volatile("fsave %[fx]; fwait"
|
asm volatile("fnsave %[fx]; fwait"
|
||||||
: [fx] "=m" (fpu->state->fsave));
|
: [fx] "=m" (fpu->state->fsave));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@@ -976,6 +976,11 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
paging_init();
|
paging_init();
|
||||||
x86_init.paging.pagetable_setup_done(swapper_pg_dir);
|
x86_init.paging.pagetable_setup_done(swapper_pg_dir);
|
||||||
|
|
||||||
|
if (boot_cpu_data.cpuid_level >= 0) {
|
||||||
|
/* A CPU has %cr4 if and only if it has CPUID */
|
||||||
|
mmu_cr4_features = read_cr4();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
/* sync back kernel address range */
|
/* sync back kernel address range */
|
||||||
clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
|
clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
|
||||||
|
@@ -211,10 +211,12 @@ int __init get_memcfg_from_srat(void)
|
|||||||
{
|
{
|
||||||
int i, j, nid;
|
int i, j, nid;
|
||||||
|
|
||||||
|
|
||||||
if (srat_disabled())
|
if (srat_disabled())
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
|
|
||||||
|
if (acpi_numa_init() < 0)
|
||||||
|
goto out_fail;
|
||||||
|
|
||||||
if (num_memory_chunks == 0) {
|
if (num_memory_chunks == 0) {
|
||||||
printk(KERN_DEBUG
|
printk(KERN_DEBUG
|
||||||
"could not find any ACPI SRAT memory areas.\n");
|
"could not find any ACPI SRAT memory areas.\n");
|
||||||
|
@@ -100,9 +100,11 @@ int vrtc_set_mmss(unsigned long nowtime)
|
|||||||
|
|
||||||
void __init mrst_rtc_init(void)
|
void __init mrst_rtc_init(void)
|
||||||
{
|
{
|
||||||
unsigned long vrtc_paddr = sfi_mrtc_array[0].phys_addr;
|
unsigned long vrtc_paddr;
|
||||||
|
|
||||||
sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
|
sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
|
||||||
|
|
||||||
|
vrtc_paddr = sfi_mrtc_array[0].phys_addr;
|
||||||
if (!sfi_mrtc_num || !vrtc_paddr)
|
if (!sfi_mrtc_num || !vrtc_paddr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -471,15 +471,7 @@ static unsigned int startup_piix4_master_irq(struct irq_data *data)
|
|||||||
{
|
{
|
||||||
legacy_pic->init(0);
|
legacy_pic->init(0);
|
||||||
enable_cobalt_irq(data);
|
enable_cobalt_irq(data);
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
static void end_piix4_master_irq(struct irq_data *data)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&cobalt_lock, flags);
|
|
||||||
enable_cobalt_irq(data);
|
|
||||||
spin_unlock_irqrestore(&cobalt_lock, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_chip piix4_master_irq_type = {
|
static struct irq_chip piix4_master_irq_type = {
|
||||||
@@ -492,7 +484,7 @@ static void pii4_mask(struct irq_data *data) { }
|
|||||||
|
|
||||||
static struct irq_chip piix4_virtual_irq_type = {
|
static struct irq_chip piix4_virtual_irq_type = {
|
||||||
.name = "PIIX4-virtual",
|
.name = "PIIX4-virtual",
|
||||||
.mask = pii4_mask,
|
.irq_mask = pii4_mask,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -580,9 +572,9 @@ static struct irqaction cascade_action = {
|
|||||||
|
|
||||||
static inline void set_piix4_virtual_irq_type(void)
|
static inline void set_piix4_virtual_irq_type(void)
|
||||||
{
|
{
|
||||||
piix4_virtual_irq_type.enable = i8259A_chip.unmask;
|
piix4_virtual_irq_type.irq_enable = i8259A_chip.irq_unmask;
|
||||||
piix4_virtual_irq_type.disable = i8259A_chip.mask;
|
piix4_virtual_irq_type.irq_disable = i8259A_chip.irq_mask;
|
||||||
piix4_virtual_irq_type.unmask = i8259A_chip.unmask;
|
piix4_virtual_irq_type.irq_unmask = i8259A_chip.irq_unmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init visws_pre_intr_init(void)
|
static void __init visws_pre_intr_init(void)
|
||||||
@@ -599,7 +591,7 @@ static void __init visws_pre_intr_init(void)
|
|||||||
else if (i == CO_IRQ_IDE0)
|
else if (i == CO_IRQ_IDE0)
|
||||||
chip = &cobalt_irq_type;
|
chip = &cobalt_irq_type;
|
||||||
else if (i == CO_IRQ_IDE1)
|
else if (i == CO_IRQ_IDE1)
|
||||||
>chip = &cobalt_irq_type;
|
chip = &cobalt_irq_type;
|
||||||
else if (i == CO_IRQ_8259)
|
else if (i == CO_IRQ_8259)
|
||||||
chip = &piix4_master_irq_type;
|
chip = &piix4_master_irq_type;
|
||||||
else if (i < CO_IRQ_APIC0)
|
else if (i < CO_IRQ_APIC0)
|
||||||
|
@@ -342,6 +342,8 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
|
|||||||
|
|
||||||
mrst_rtc.irq = rtc_irq;
|
mrst_rtc.irq = rtc_irq;
|
||||||
mrst_rtc.iomem = iomem;
|
mrst_rtc.iomem = iomem;
|
||||||
|
mrst_rtc.dev = dev;
|
||||||
|
dev_set_drvdata(dev, &mrst_rtc);
|
||||||
|
|
||||||
mrst_rtc.rtc = rtc_device_register(driver_name, dev,
|
mrst_rtc.rtc = rtc_device_register(driver_name, dev,
|
||||||
&mrst_rtc_ops, THIS_MODULE);
|
&mrst_rtc_ops, THIS_MODULE);
|
||||||
@@ -350,8 +352,6 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
|
|||||||
goto cleanup0;
|
goto cleanup0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mrst_rtc.dev = dev;
|
|
||||||
dev_set_drvdata(dev, &mrst_rtc);
|
|
||||||
rename_region(iomem, dev_name(&mrst_rtc.rtc->dev));
|
rename_region(iomem, dev_name(&mrst_rtc.rtc->dev));
|
||||||
|
|
||||||
spin_lock_irq(&rtc_lock);
|
spin_lock_irq(&rtc_lock);
|
||||||
@@ -376,9 +376,10 @@ vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cleanup1:
|
cleanup1:
|
||||||
mrst_rtc.dev = NULL;
|
|
||||||
rtc_device_unregister(mrst_rtc.rtc);
|
rtc_device_unregister(mrst_rtc.rtc);
|
||||||
cleanup0:
|
cleanup0:
|
||||||
|
dev_set_drvdata(dev, NULL);
|
||||||
|
mrst_rtc.dev = NULL;
|
||||||
release_region(iomem->start, iomem->end + 1 - iomem->start);
|
release_region(iomem->start, iomem->end + 1 - iomem->start);
|
||||||
dev_err(dev, "rtc-mrst: unable to initialise\n");
|
dev_err(dev, "rtc-mrst: unable to initialise\n");
|
||||||
return retval;
|
return retval;
|
||||||
|
@@ -1051,6 +1051,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
|
|||||||
register_irq_proc(irq, desc);
|
register_irq_proc(irq, desc);
|
||||||
new->dir = NULL;
|
new->dir = NULL;
|
||||||
register_handler_proc(irq, new);
|
register_handler_proc(irq, new);
|
||||||
|
free_cpumask_var(mask);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@@ -6331,6 +6331,9 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_max_interval();
|
||||||
|
|
||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3820,6 +3820,17 @@ void select_nohz_load_balancer(int stop_tick)
|
|||||||
|
|
||||||
static DEFINE_SPINLOCK(balancing);
|
static DEFINE_SPINLOCK(balancing);
|
||||||
|
|
||||||
|
static unsigned long __read_mostly max_load_balance_interval = HZ/10;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scale the max load_balance interval with the number of CPUs in the system.
|
||||||
|
* This trades load-balance latency on larger machines for less cross talk.
|
||||||
|
*/
|
||||||
|
static void update_max_interval(void)
|
||||||
|
{
|
||||||
|
max_load_balance_interval = HZ*num_online_cpus()/10;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It checks each scheduling domain to see if it is due to be balanced,
|
* It checks each scheduling domain to see if it is due to be balanced,
|
||||||
* and initiates a balancing operation if so.
|
* and initiates a balancing operation if so.
|
||||||
@@ -3849,10 +3860,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
|
|||||||
|
|
||||||
/* scale ms to jiffies */
|
/* scale ms to jiffies */
|
||||||
interval = msecs_to_jiffies(interval);
|
interval = msecs_to_jiffies(interval);
|
||||||
if (unlikely(!interval))
|
interval = clamp(interval, 1UL, max_load_balance_interval);
|
||||||
interval = 1;
|
|
||||||
if (interval > HZ*num_online_cpus()/10)
|
|
||||||
interval = HZ*num_online_cpus()/10;
|
|
||||||
|
|
||||||
need_serialize = sd->flags & SD_SERIALIZE;
|
need_serialize = sd->flags & SD_SERIALIZE;
|
||||||
|
|
||||||
|
@@ -234,7 +234,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
|
|||||||
|
|
||||||
/* Searching trace events corresponding to probe event */
|
/* Searching trace events corresponding to probe event */
|
||||||
ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs);
|
ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs);
|
||||||
close(fd);
|
|
||||||
|
|
||||||
if (ntevs > 0) { /* Succeeded to find trace events */
|
if (ntevs > 0) { /* Succeeded to find trace events */
|
||||||
pr_debug("find %d probe_trace_events.\n", ntevs);
|
pr_debug("find %d probe_trace_events.\n", ntevs);
|
||||||
@@ -388,7 +387,6 @@ int show_line_range(struct line_range *lr, const char *module)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = find_line_range(fd, lr);
|
ret = find_line_range(fd, lr);
|
||||||
close(fd);
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
pr_warning("Specified source line is not found.\n");
|
pr_warning("Specified source line is not found.\n");
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@@ -512,19 +510,18 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
fd = open_vmlinux(module);
|
|
||||||
if (fd < 0) {
|
|
||||||
pr_warning("Failed to open debug information file.\n");
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_pager();
|
setup_pager();
|
||||||
|
|
||||||
for (i = 0; i < npevs && ret >= 0; i++)
|
for (i = 0; i < npevs && ret >= 0; i++) {
|
||||||
|
fd = open_vmlinux(module);
|
||||||
|
if (fd < 0) {
|
||||||
|
pr_warning("Failed to open debug information file.\n");
|
||||||
|
ret = fd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
|
ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
|
||||||
externs);
|
externs);
|
||||||
|
}
|
||||||
close(fd);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -273,6 +273,25 @@ static const char *cu_get_comp_dir(Dwarf_Die *cu_die)
|
|||||||
return dwarf_formstring(&attr);
|
return dwarf_formstring(&attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get a line number and file name for given address */
|
||||||
|
static int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
|
||||||
|
const char **fname, int *lineno)
|
||||||
|
{
|
||||||
|
Dwarf_Line *line;
|
||||||
|
Dwarf_Addr laddr;
|
||||||
|
|
||||||
|
line = dwarf_getsrc_die(cudie, (Dwarf_Addr)addr);
|
||||||
|
if (line && dwarf_lineaddr(line, &laddr) == 0 &&
|
||||||
|
addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
|
||||||
|
*fname = dwarf_linesrc(line, NULL, NULL);
|
||||||
|
if (!*fname)
|
||||||
|
/* line number is useless without filename */
|
||||||
|
*lineno = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *lineno ?: -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compare diename and tname */
|
/* Compare diename and tname */
|
||||||
static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
|
static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
|
||||||
{
|
{
|
||||||
@@ -497,7 +516,20 @@ static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
|
|||||||
static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
|
static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
|
||||||
Dwarf_Die *die_mem)
|
Dwarf_Die *die_mem)
|
||||||
{
|
{
|
||||||
return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
|
Dwarf_Die tmp_die;
|
||||||
|
|
||||||
|
sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
|
||||||
|
if (!sp_die)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Inlined function could be recursive. Trace it until fail */
|
||||||
|
while (sp_die) {
|
||||||
|
memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
|
||||||
|
sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
|
||||||
|
&tmp_die);
|
||||||
|
}
|
||||||
|
|
||||||
|
return die_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Walker on lines (Note: line number will not be sorted) */
|
/* Walker on lines (Note: line number will not be sorted) */
|
||||||
@@ -1395,6 +1427,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
|
|||||||
!die_compare_name(sp_die, pp->function))
|
!die_compare_name(sp_die, pp->function))
|
||||||
return DWARF_CB_OK;
|
return DWARF_CB_OK;
|
||||||
|
|
||||||
|
/* Check declared file */
|
||||||
|
if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
|
||||||
|
return DWARF_CB_OK;
|
||||||
|
|
||||||
pf->fname = dwarf_decl_file(sp_die);
|
pf->fname = dwarf_decl_file(sp_die);
|
||||||
if (pp->line) { /* Function relative line */
|
if (pp->line) { /* Function relative line */
|
||||||
dwarf_decl_line(sp_die, &pf->lno);
|
dwarf_decl_line(sp_die, &pf->lno);
|
||||||
@@ -1451,6 +1487,7 @@ static int find_probes(int fd, struct probe_finder *pf)
|
|||||||
if (!dbg) {
|
if (!dbg) {
|
||||||
pr_warning("No debug information found in the vmlinux - "
|
pr_warning("No debug information found in the vmlinux - "
|
||||||
"please rebuild with CONFIG_DEBUG_INFO=y.\n");
|
"please rebuild with CONFIG_DEBUG_INFO=y.\n");
|
||||||
|
close(fd); /* Without dwfl_end(), fd isn't closed. */
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1686,11 +1723,9 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
|
|||||||
Dwarf_Die cudie, spdie, indie;
|
Dwarf_Die cudie, spdie, indie;
|
||||||
Dwarf *dbg = NULL;
|
Dwarf *dbg = NULL;
|
||||||
Dwfl *dwfl = NULL;
|
Dwfl *dwfl = NULL;
|
||||||
Dwarf_Line *line;
|
Dwarf_Addr _addr, baseaddr, bias = 0;
|
||||||
Dwarf_Addr laddr, eaddr, bias = 0;
|
const char *fname = NULL, *func = NULL, *tmp;
|
||||||
const char *tmp;
|
int baseline = 0, lineno = 0, ret = 0;
|
||||||
int lineno, ret = 0;
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
/* Open the live linux kernel */
|
/* Open the live linux kernel */
|
||||||
dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
|
dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
|
||||||
@@ -1711,68 +1746,79 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a corresponding line */
|
/* Find a corresponding line (filename and lineno) */
|
||||||
line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr);
|
cu_find_lineinfo(&cudie, addr, &fname, &lineno);
|
||||||
if (line) {
|
/* Don't care whether it failed or not */
|
||||||
if (dwarf_lineaddr(line, &laddr) == 0 &&
|
|
||||||
(Dwarf_Addr)addr == laddr &&
|
/* Find a corresponding function (name, baseline and baseaddr) */
|
||||||
dwarf_lineno(line, &lineno) == 0) {
|
if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
|
||||||
tmp = dwarf_linesrc(line, NULL, NULL);
|
/* Get function entry information */
|
||||||
if (tmp) {
|
tmp = dwarf_diename(&spdie);
|
||||||
ppt->line = lineno;
|
if (!tmp ||
|
||||||
ppt->file = strdup(tmp);
|
dwarf_entrypc(&spdie, &baseaddr) != 0 ||
|
||||||
if (ppt->file == NULL) {
|
dwarf_decl_line(&spdie, &baseline) != 0)
|
||||||
ret = -ENOMEM;
|
goto post;
|
||||||
goto end;
|
func = tmp;
|
||||||
}
|
|
||||||
found = true;
|
if (addr == (unsigned long)baseaddr)
|
||||||
|
/* Function entry - Relative line number is 0 */
|
||||||
|
lineno = baseline;
|
||||||
|
else if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
|
||||||
|
&indie)) {
|
||||||
|
if (dwarf_entrypc(&indie, &_addr) == 0 &&
|
||||||
|
_addr == addr)
|
||||||
|
/*
|
||||||
|
* addr is at an inline function entry.
|
||||||
|
* In this case, lineno should be the call-site
|
||||||
|
* line number.
|
||||||
|
*/
|
||||||
|
lineno = die_get_call_lineno(&indie);
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* addr is in an inline function body.
|
||||||
|
* Since lineno points one of the lines
|
||||||
|
* of the inline function, baseline should
|
||||||
|
* be the entry line of the inline function.
|
||||||
|
*/
|
||||||
|
tmp = dwarf_diename(&indie);
|
||||||
|
if (tmp &&
|
||||||
|
dwarf_decl_line(&spdie, &baseline) == 0)
|
||||||
|
func = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a corresponding function */
|
post:
|
||||||
if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
|
/* Make a relative line number or an offset */
|
||||||
tmp = dwarf_diename(&spdie);
|
if (lineno)
|
||||||
if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0)
|
ppt->line = lineno - baseline;
|
||||||
goto end;
|
else if (func)
|
||||||
|
ppt->offset = addr - (unsigned long)baseaddr;
|
||||||
|
|
||||||
if (ppt->line) {
|
/* Duplicate strings */
|
||||||
if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
|
if (func) {
|
||||||
&indie)) {
|
ppt->function = strdup(func);
|
||||||
/* addr in an inline function */
|
|
||||||
tmp = dwarf_diename(&indie);
|
|
||||||
if (!tmp)
|
|
||||||
goto end;
|
|
||||||
ret = dwarf_decl_line(&indie, &lineno);
|
|
||||||
} else {
|
|
||||||
if (eaddr == addr) { /* Function entry */
|
|
||||||
lineno = ppt->line;
|
|
||||||
ret = 0;
|
|
||||||
} else
|
|
||||||
ret = dwarf_decl_line(&spdie, &lineno);
|
|
||||||
}
|
|
||||||
if (ret == 0) {
|
|
||||||
/* Make a relative line number */
|
|
||||||
ppt->line -= lineno;
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* We don't have a line number, let's use offset */
|
|
||||||
ppt->offset = addr - (unsigned long)eaddr;
|
|
||||||
found:
|
|
||||||
ppt->function = strdup(tmp);
|
|
||||||
if (ppt->function == NULL) {
|
if (ppt->function == NULL) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
found = true;
|
|
||||||
}
|
}
|
||||||
|
if (fname) {
|
||||||
|
ppt->file = strdup(fname);
|
||||||
|
if (ppt->file == NULL) {
|
||||||
|
if (ppt->function) {
|
||||||
|
free(ppt->function);
|
||||||
|
ppt->function = NULL;
|
||||||
|
}
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
end:
|
end:
|
||||||
if (dwfl)
|
if (dwfl)
|
||||||
dwfl_end(dwfl);
|
dwfl_end(dwfl);
|
||||||
if (ret >= 0)
|
if (ret == 0 && (fname || func))
|
||||||
ret = found ? 1 : 0;
|
ret = 1; /* Found a point */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1840,6 +1886,10 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
|
|||||||
struct line_finder *lf = param->data;
|
struct line_finder *lf = param->data;
|
||||||
struct line_range *lr = lf->lr;
|
struct line_range *lr = lf->lr;
|
||||||
|
|
||||||
|
/* Check declared file */
|
||||||
|
if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
|
||||||
|
return DWARF_CB_OK;
|
||||||
|
|
||||||
if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
|
if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
|
||||||
die_compare_name(sp_die, lr->function)) {
|
die_compare_name(sp_die, lr->function)) {
|
||||||
lf->fname = dwarf_decl_file(sp_die);
|
lf->fname = dwarf_decl_file(sp_die);
|
||||||
@@ -1892,6 +1942,7 @@ int find_line_range(int fd, struct line_range *lr)
|
|||||||
if (!dbg) {
|
if (!dbg) {
|
||||||
pr_warning("No debug information found in the vmlinux - "
|
pr_warning("No debug information found in the vmlinux - "
|
||||||
"please rebuild with CONFIG_DEBUG_INFO=y.\n");
|
"please rebuild with CONFIG_DEBUG_INFO=y.\n");
|
||||||
|
close(fd); /* Without dwfl_end(), fd isn't closed. */
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user