diff options
Diffstat (limited to 'tools/perf/util/jitdump.c')
| -rw-r--r-- | tools/perf/util/jitdump.c | 82 | 
1 files changed, 72 insertions, 10 deletions
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 95f0884aae02..c9a941ef0f6d 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -37,6 +37,10 @@ struct jit_buf_desc {  	bool		 needs_bswap; /* handles cross-endianess */  	bool		 use_arch_timestamp;  	void		 *debug_data; +	void		 *unwinding_data; +	uint64_t	 unwinding_size; +	uint64_t	 unwinding_mapped_size; +	uint64_t         eh_frame_hdr_size;  	size_t		 nr_debug_entries;  	uint32_t         code_load_count;  	u64		 bytes_written; @@ -68,7 +72,10 @@ jit_emit_elf(char *filename,  	     const void *code,  	     int csize,  	     void *debug, -	     int nr_debug_entries) +	     int nr_debug_entries, +	     void *unwinding, +	     uint32_t unwinding_header_size, +	     uint32_t unwinding_size)  {  	int ret, fd; @@ -81,7 +88,8 @@ jit_emit_elf(char *filename,  		return -1;  	} -        ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize, debug, nr_debug_entries); +	ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize, debug, nr_debug_entries, +			    unwinding, unwinding_header_size, unwinding_size);          close(fd); @@ -172,6 +180,12 @@ jit_open(struct jit_buf_desc *jd, const char *name)  			header.elf_mach,  			jd->use_arch_timestamp); +	if (header.version > JITHEADER_VERSION) { +		pr_err("wrong jitdump version %u, expected " STR(JITHEADER_VERSION), +			header.version); +		goto error; +	} +  	if (header.flags & JITDUMP_FLAGS_RESERVED) {  		pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",  		       (unsigned long long)header.flags & JITDUMP_FLAGS_RESERVED); @@ -263,8 +277,7 @@ jit_get_next_entry(struct jit_buf_desc *jd)  		return NULL;  	if (id >= JIT_CODE_MAX) { -		pr_warning("next_entry: unknown prefix %d, skipping\n", id); -		return NULL; +		pr_warning("next_entry: unknown record type %d, skipping\n", id);  	}  	if (bs > jd->bufsize) {  		void *n; @@ -296,6 +309,13 @@ jit_get_next_entry(struct jit_buf_desc *jd)  			}  		}  		break; +	case JIT_CODE_UNWINDING_INFO: +		if (jd->needs_bswap) { +			jr->unwinding.unwinding_size = bswap_64(jr->unwinding.unwinding_size); +			jr->unwinding.eh_frame_hdr_size = bswap_64(jr->unwinding.eh_frame_hdr_size); +			jr->unwinding.mapped_size = bswap_64(jr->unwinding.mapped_size); +		} +		break;  	case JIT_CODE_CLOSE:  		break;  	case JIT_CODE_LOAD: @@ -322,7 +342,8 @@ jit_get_next_entry(struct jit_buf_desc *jd)  		break;  	case JIT_CODE_MAX:  	default: -		return NULL; +		/* skip unknown record (we have read them) */ +		break;  	}  	return jr;  } @@ -370,7 +391,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)  	u16 idr_size;  	const char *sym;  	uint32_t count; -	int ret, csize; +	int ret, csize, usize;  	pid_t pid, tid;  	struct {  		u32 pid, tid; @@ -380,6 +401,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)  	pid   = jr->load.pid;  	tid   = jr->load.tid;  	csize = jr->load.code_size; +	usize = jd->unwinding_mapped_size;  	addr  = jr->load.code_addr;  	sym   = (void *)((unsigned long)jr + sizeof(jr->load));  	code  = (unsigned long)jr + jr->load.p.total_size - csize; @@ -400,7 +422,8 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)  	size = PERF_ALIGN(size, sizeof(u64));  	uaddr = (uintptr_t)code; -	ret = jit_emit_elf(filename, sym, addr, (const void *)uaddr, csize, jd->debug_data, jd->nr_debug_entries); +	ret = jit_emit_elf(filename, sym, addr, (const void *)uaddr, csize, jd->debug_data, jd->nr_debug_entries, +			   jd->unwinding_data, jd->eh_frame_hdr_size, jd->unwinding_size);  	if (jd->debug_data && jd->nr_debug_entries) {  		free(jd->debug_data); @@ -408,6 +431,14 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)  		jd->nr_debug_entries = 0;  	} +	if (jd->unwinding_data && jd->eh_frame_hdr_size) { +		free(jd->unwinding_data); +		jd->unwinding_data = NULL; +		jd->eh_frame_hdr_size = 0; +		jd->unwinding_mapped_size = 0; +		jd->unwinding_size = 0; +	} +  	if (ret) {  		free(event);  		return -1; @@ -422,7 +453,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)  	event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET;  	event->mmap2.start = addr; -	event->mmap2.len   = csize; +	event->mmap2.len   = usize ? ALIGN_8(csize) + usize : csize;  	event->mmap2.pid   = pid;  	event->mmap2.tid   = tid;  	event->mmap2.ino   = st.st_ino; @@ -473,6 +504,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)  	char *filename;  	size_t size;  	struct stat st; +	int usize;  	u16 idr_size;  	int ret;  	pid_t pid, tid; @@ -483,6 +515,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)  	pid = jr->move.pid;  	tid =  jr->move.tid; +	usize = jd->unwinding_mapped_size;  	idr_size = jd->machine->id_hdr_size;  	/* @@ -511,7 +544,8 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)  			(sizeof(event->mmap2.filename) - size) + idr_size);  	event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET;  	event->mmap2.start = jr->move.new_code_addr; -	event->mmap2.len   = jr->move.code_size; +	event->mmap2.len   = usize ? ALIGN_8(jr->move.code_size) + usize +				   : jr->move.code_size;  	event->mmap2.pid   = pid;  	event->mmap2.tid   = tid;  	event->mmap2.ino   = st.st_ino; @@ -578,10 +612,35 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr)  }  static int +jit_repipe_unwinding_info(struct jit_buf_desc *jd, union jr_entry *jr) +{ +	void *unwinding_data; +	uint32_t unwinding_data_size; + +	if (!(jd && jr)) +		return -1; + +	unwinding_data_size  = jr->prefix.total_size - sizeof(jr->unwinding); +	unwinding_data = malloc(unwinding_data_size); +	if (!unwinding_data) +		return -1; + +	memcpy(unwinding_data, &jr->unwinding.unwinding_data, +	       unwinding_data_size); + +	jd->eh_frame_hdr_size = jr->unwinding.eh_frame_hdr_size; +	jd->unwinding_size = jr->unwinding.unwinding_size; +	jd->unwinding_mapped_size = jr->unwinding.mapped_size; +	jd->unwinding_data = unwinding_data; + +	return 0; +} + +static int  jit_process_dump(struct jit_buf_desc *jd)  {  	union jr_entry *jr; -	int ret; +	int ret = 0;  	while ((jr = jit_get_next_entry(jd))) {  		switch(jr->prefix.id) { @@ -594,6 +653,9 @@ jit_process_dump(struct jit_buf_desc *jd)  		case JIT_CODE_DEBUG_INFO:  			ret = jit_repipe_debug_info(jd, jr);  			break; +		case JIT_CODE_UNWINDING_INFO: +			ret = jit_repipe_unwinding_info(jd, jr); +			break;  		default:  			ret = 0;  			continue;  |