mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-10-28 23:08:52 +01:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
14
tools/perf/arch/arm/Makefile
Normal file
14
tools/perf/arch/arm/Makefile
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
ifndef NO_DWARF
|
||||
PERF_HAVE_DWARF_REGS := 1
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
|
||||
endif
|
||||
ifndef NO_LIBUNWIND
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
|
||||
endif
|
||||
ifndef NO_LIBDW_DWARF_UNWIND
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o
|
||||
endif
|
||||
ifndef NO_DWARF_UNWIND
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o
|
||||
endif
|
||||
59
tools/perf/arch/arm/include/perf_regs.h
Normal file
59
tools/perf/arch/arm/include/perf_regs.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#ifndef ARCH_PERF_REGS_H
|
||||
#define ARCH_PERF_REGS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/perf_regs.h>
|
||||
|
||||
void perf_regs_load(u64 *regs);
|
||||
|
||||
#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM_MAX) - 1)
|
||||
#define PERF_REGS_MAX PERF_REG_ARM_MAX
|
||||
#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32
|
||||
|
||||
#define PERF_REG_IP PERF_REG_ARM_PC
|
||||
#define PERF_REG_SP PERF_REG_ARM_SP
|
||||
|
||||
static inline const char *perf_reg_name(int id)
|
||||
{
|
||||
switch (id) {
|
||||
case PERF_REG_ARM_R0:
|
||||
return "r0";
|
||||
case PERF_REG_ARM_R1:
|
||||
return "r1";
|
||||
case PERF_REG_ARM_R2:
|
||||
return "r2";
|
||||
case PERF_REG_ARM_R3:
|
||||
return "r3";
|
||||
case PERF_REG_ARM_R4:
|
||||
return "r4";
|
||||
case PERF_REG_ARM_R5:
|
||||
return "r5";
|
||||
case PERF_REG_ARM_R6:
|
||||
return "r6";
|
||||
case PERF_REG_ARM_R7:
|
||||
return "r7";
|
||||
case PERF_REG_ARM_R8:
|
||||
return "r8";
|
||||
case PERF_REG_ARM_R9:
|
||||
return "r9";
|
||||
case PERF_REG_ARM_R10:
|
||||
return "r10";
|
||||
case PERF_REG_ARM_FP:
|
||||
return "fp";
|
||||
case PERF_REG_ARM_IP:
|
||||
return "ip";
|
||||
case PERF_REG_ARM_SP:
|
||||
return "sp";
|
||||
case PERF_REG_ARM_LR:
|
||||
return "lr";
|
||||
case PERF_REG_ARM_PC:
|
||||
return "pc";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* ARCH_PERF_REGS_H */
|
||||
61
tools/perf/arch/arm/tests/dwarf-unwind.c
Normal file
61
tools/perf/arch/arm/tests/dwarf-unwind.c
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#include <string.h>
|
||||
#include "perf_regs.h"
|
||||
#include "thread.h"
|
||||
#include "map.h"
|
||||
#include "event.h"
|
||||
#include "debug.h"
|
||||
#include "tests/tests.h"
|
||||
|
||||
#define STACK_SIZE 8192
|
||||
|
||||
static int sample_ustack(struct perf_sample *sample,
|
||||
struct thread *thread, u64 *regs)
|
||||
{
|
||||
struct stack_dump *stack = &sample->user_stack;
|
||||
struct map *map;
|
||||
unsigned long sp;
|
||||
u64 stack_size, *buf;
|
||||
|
||||
buf = malloc(STACK_SIZE);
|
||||
if (!buf) {
|
||||
pr_debug("failed to allocate sample uregs data\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sp = (unsigned long) regs[PERF_REG_ARM_SP];
|
||||
|
||||
map = map_groups__find(thread->mg, MAP__VARIABLE, (u64) sp);
|
||||
if (!map) {
|
||||
pr_debug("failed to get stack map\n");
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
stack_size = map->end - sp;
|
||||
stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size;
|
||||
|
||||
memcpy(buf, (void *) sp, stack_size);
|
||||
stack->data = (char *) buf;
|
||||
stack->size = stack_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test__arch_unwind_sample(struct perf_sample *sample,
|
||||
struct thread *thread)
|
||||
{
|
||||
struct regs_dump *regs = &sample->user_regs;
|
||||
u64 *buf;
|
||||
|
||||
buf = calloc(1, sizeof(u64) * PERF_REGS_MAX);
|
||||
if (!buf) {
|
||||
pr_debug("failed to allocate sample uregs data\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
perf_regs_load(buf);
|
||||
regs->abi = PERF_SAMPLE_REGS_ABI;
|
||||
regs->regs = buf;
|
||||
regs->mask = PERF_REGS_MASK;
|
||||
|
||||
return sample_ustack(sample, thread, buf);
|
||||
}
|
||||
58
tools/perf/arch/arm/tests/regs_load.S
Normal file
58
tools/perf/arch/arm/tests/regs_load.S
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#include <linux/linkage.h>
|
||||
|
||||
#define R0 0x00
|
||||
#define R1 0x08
|
||||
#define R2 0x10
|
||||
#define R3 0x18
|
||||
#define R4 0x20
|
||||
#define R5 0x28
|
||||
#define R6 0x30
|
||||
#define R7 0x38
|
||||
#define R8 0x40
|
||||
#define R9 0x48
|
||||
#define SL 0x50
|
||||
#define FP 0x58
|
||||
#define IP 0x60
|
||||
#define SP 0x68
|
||||
#define LR 0x70
|
||||
#define PC 0x78
|
||||
|
||||
/*
|
||||
* Implementation of void perf_regs_load(u64 *regs);
|
||||
*
|
||||
* This functions fills in the 'regs' buffer from the actual registers values,
|
||||
* in the way the perf built-in unwinding test expects them:
|
||||
* - the PC at the time at the call to this function. Since this function
|
||||
* is called using a bl instruction, the PC value is taken from LR.
|
||||
* The built-in unwinding test then unwinds the call stack from the dwarf
|
||||
* information in unwind__get_entries.
|
||||
*
|
||||
* Notes:
|
||||
* - the 8 bytes stride in the registers offsets comes from the fact
|
||||
* that the registers are stored in an u64 array (u64 *regs),
|
||||
* - the regs buffer needs to be zeroed before the call to this function,
|
||||
* in this case using a calloc in dwarf-unwind.c.
|
||||
*/
|
||||
|
||||
.text
|
||||
.type perf_regs_load,%function
|
||||
ENTRY(perf_regs_load)
|
||||
str r0, [r0, #R0]
|
||||
str r1, [r0, #R1]
|
||||
str r2, [r0, #R2]
|
||||
str r3, [r0, #R3]
|
||||
str r4, [r0, #R4]
|
||||
str r5, [r0, #R5]
|
||||
str r6, [r0, #R6]
|
||||
str r7, [r0, #R7]
|
||||
str r8, [r0, #R8]
|
||||
str r9, [r0, #R9]
|
||||
str sl, [r0, #SL]
|
||||
str fp, [r0, #FP]
|
||||
str ip, [r0, #IP]
|
||||
str sp, [r0, #SP]
|
||||
str lr, [r0, #LR]
|
||||
str lr, [r0, #PC] // store pc as lr in order to skip the call
|
||||
// to this function
|
||||
mov pc, lr
|
||||
ENDPROC(perf_regs_load)
|
||||
64
tools/perf/arch/arm/util/dwarf-regs.c
Normal file
64
tools/perf/arch/arm/util/dwarf-regs.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Mapping of DWARF debug register numbers into register names.
|
||||
*
|
||||
* Copyright (C) 2010 Will Deacon, ARM Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <dwarf-regs.h>
|
||||
|
||||
struct pt_regs_dwarfnum {
|
||||
const char *name;
|
||||
unsigned int dwarfnum;
|
||||
};
|
||||
|
||||
#define STR(s) #s
|
||||
#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
|
||||
#define GPR_DWARFNUM_NAME(num) \
|
||||
{.name = STR(%r##num), .dwarfnum = num}
|
||||
#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
|
||||
|
||||
/*
|
||||
* Reference:
|
||||
* http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040a/IHI0040A_aadwarf.pdf
|
||||
*/
|
||||
static const struct pt_regs_dwarfnum regdwarfnum_table[] = {
|
||||
GPR_DWARFNUM_NAME(0),
|
||||
GPR_DWARFNUM_NAME(1),
|
||||
GPR_DWARFNUM_NAME(2),
|
||||
GPR_DWARFNUM_NAME(3),
|
||||
GPR_DWARFNUM_NAME(4),
|
||||
GPR_DWARFNUM_NAME(5),
|
||||
GPR_DWARFNUM_NAME(6),
|
||||
GPR_DWARFNUM_NAME(7),
|
||||
GPR_DWARFNUM_NAME(8),
|
||||
GPR_DWARFNUM_NAME(9),
|
||||
GPR_DWARFNUM_NAME(10),
|
||||
REG_DWARFNUM_NAME("%fp", 11),
|
||||
REG_DWARFNUM_NAME("%ip", 12),
|
||||
REG_DWARFNUM_NAME("%sp", 13),
|
||||
REG_DWARFNUM_NAME("%lr", 14),
|
||||
REG_DWARFNUM_NAME("%pc", 15),
|
||||
REG_DWARFNUM_END,
|
||||
};
|
||||
|
||||
/**
|
||||
* get_arch_regstr() - lookup register name from it's DWARF register number
|
||||
* @n: the DWARF register number
|
||||
*
|
||||
* get_arch_regstr() returns the name of the register in struct
|
||||
* regdwarfnum_table from it's DWARF register number. If the register is not
|
||||
* found in the table, this returns NULL;
|
||||
*/
|
||||
const char *get_arch_regstr(unsigned int n)
|
||||
{
|
||||
const struct pt_regs_dwarfnum *roff;
|
||||
for (roff = regdwarfnum_table; roff->name != NULL; roff++)
|
||||
if (roff->dwarfnum == n)
|
||||
return roff->name;
|
||||
return NULL;
|
||||
}
|
||||
36
tools/perf/arch/arm/util/unwind-libdw.c
Normal file
36
tools/perf/arch/arm/util/unwind-libdw.c
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#include <elfutils/libdwfl.h>
|
||||
#include "../../util/unwind-libdw.h"
|
||||
#include "../../util/perf_regs.h"
|
||||
|
||||
bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
|
||||
{
|
||||
struct unwind_info *ui = arg;
|
||||
struct regs_dump *user_regs = &ui->sample->user_regs;
|
||||
Dwarf_Word dwarf_regs[PERF_REG_ARM_MAX];
|
||||
|
||||
#define REG(r) ({ \
|
||||
Dwarf_Word val = 0; \
|
||||
perf_reg_value(&val, user_regs, PERF_REG_ARM_##r); \
|
||||
val; \
|
||||
})
|
||||
|
||||
dwarf_regs[0] = REG(R0);
|
||||
dwarf_regs[1] = REG(R1);
|
||||
dwarf_regs[2] = REG(R2);
|
||||
dwarf_regs[3] = REG(R3);
|
||||
dwarf_regs[4] = REG(R4);
|
||||
dwarf_regs[5] = REG(R5);
|
||||
dwarf_regs[6] = REG(R6);
|
||||
dwarf_regs[7] = REG(R7);
|
||||
dwarf_regs[8] = REG(R8);
|
||||
dwarf_regs[9] = REG(R9);
|
||||
dwarf_regs[10] = REG(R10);
|
||||
dwarf_regs[11] = REG(FP);
|
||||
dwarf_regs[12] = REG(IP);
|
||||
dwarf_regs[13] = REG(SP);
|
||||
dwarf_regs[14] = REG(LR);
|
||||
dwarf_regs[15] = REG(PC);
|
||||
|
||||
return dwfl_thread_state_registers(thread, 0, PERF_REG_ARM_MAX,
|
||||
dwarf_regs);
|
||||
}
|
||||
49
tools/perf/arch/arm/util/unwind-libunwind.c
Normal file
49
tools/perf/arch/arm/util/unwind-libunwind.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <libunwind.h>
|
||||
#include "perf_regs.h"
|
||||
#include "../../util/unwind.h"
|
||||
#include "../../util/debug.h"
|
||||
|
||||
int libunwind__arch_reg_id(int regnum)
|
||||
{
|
||||
switch (regnum) {
|
||||
case UNW_ARM_R0:
|
||||
return PERF_REG_ARM_R0;
|
||||
case UNW_ARM_R1:
|
||||
return PERF_REG_ARM_R1;
|
||||
case UNW_ARM_R2:
|
||||
return PERF_REG_ARM_R2;
|
||||
case UNW_ARM_R3:
|
||||
return PERF_REG_ARM_R3;
|
||||
case UNW_ARM_R4:
|
||||
return PERF_REG_ARM_R4;
|
||||
case UNW_ARM_R5:
|
||||
return PERF_REG_ARM_R5;
|
||||
case UNW_ARM_R6:
|
||||
return PERF_REG_ARM_R6;
|
||||
case UNW_ARM_R7:
|
||||
return PERF_REG_ARM_R7;
|
||||
case UNW_ARM_R8:
|
||||
return PERF_REG_ARM_R8;
|
||||
case UNW_ARM_R9:
|
||||
return PERF_REG_ARM_R9;
|
||||
case UNW_ARM_R10:
|
||||
return PERF_REG_ARM_R10;
|
||||
case UNW_ARM_R11:
|
||||
return PERF_REG_ARM_FP;
|
||||
case UNW_ARM_R12:
|
||||
return PERF_REG_ARM_IP;
|
||||
case UNW_ARM_R13:
|
||||
return PERF_REG_ARM_SP;
|
||||
case UNW_ARM_R14:
|
||||
return PERF_REG_ARM_LR;
|
||||
case UNW_ARM_R15:
|
||||
return PERF_REG_ARM_PC;
|
||||
default:
|
||||
pr_err("unwind: invalid reg id %d\n", regnum);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue