On Wed, Nov 14, 2012 at 6:04 AM, Arun KS <arunks.li...@gmail.com> wrote:
> Hello,
>
> I m trying to capture and decode PTM trace from Cortex A9 dual core.
>
> I m successful  in configuring the driver(arch/arm/kernel/etm.c) and
> setting the funnel to get data in ETB.
> But I don't know how to decode these traces.
>
> Anyone has any pointers?
>
> Thanks,
> Arun

I attached some tools I use to decode the traces. I have used this on
the A8, A9 and A15. I assume since you cc-ed me you have already
applied the kernel patches I posted a while back. Without them you
will not get useful trace data from a dual core processor.

-- 
Arve Hjønnevåg
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <getopt.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#define false (0)
#define true (1)
typedef int bool;

struct state {
	uint8_t data;
	uint32_t iaddr;
	uint32_t iaddr_valid;
	uint64_t timestamp;
	int wait_count;
	unsigned int long_wait;
	uint32_t pc; // best guess
	int branch_count;
	int mode; // 2 ARM, 1 Thumb, 0 Jazelle
	int sync;
	uint8_t formatter_packet[16];
	int formatter_index;
	int sourceid;

	int contextid_bytes;
	int sourceid_match;
	bool cycle_accurate;
	bool alt_branch;
	bool program_flow_only;
	bool print_input;
	bool formatter;
};

struct packet_type {
	uint8_t match_mask;
	uint8_t match_val;
	uint8_t nonzero_mask;
	int (*decode)(struct state *state);
	const char *name;
};

static int get_byte_from_formatter(struct state *state)
{
	int ch;
	int i;
	int ebit;
	int sourceid = state->sourceid;

	while (1) {
		if (!state->formatter_index) {
			if (state->print_input)
				printf("raw:");
			for (i = 0; i < 16; i++) {
				ch = getchar();
				if (ch < 0)
					return ch;
				if (state->print_input)
					printf(" %02x%s", ch, (!(i & 1) && (ch & 1)) ? "(ID)" : "");
				state->formatter_packet[i] = ch;
			}
			if (state->print_input)
				printf("\n");
		}
		i = state->formatter_index;
		ch = state->formatter_packet[i];
		state->formatter_index = (i + 1) % 15;
		if (!(i & 1)) {
			ebit = (state->formatter_packet[15] >> (i / 2)) & 1;
			if (ch & 1) {
				ch >>= 1;
				if (state->sourceid != ch) {
					printf("New ID %x %d\n", ch, ebit);
					state->sourceid = ch;
					if (!ebit)
						sourceid = ch;
				}
				continue;
			}
			ch = ch | ebit;
		}
		if ((1 << sourceid) & state->sourceid_match)
			return ch;
		if (state->print_input)
			printf("%02x ignored source %x\n", ch, sourceid);
		sourceid = state->sourceid;
	}
}

static int get_byte(struct state *state)
{
	int i;
	int ch;

	if (state->formatter)
		ch = get_byte_from_formatter(state);
	else
		ch = getchar();
	if (ch < 0) {
		if (state->wait_count)
			printf(" Waited %d", state->wait_count);
		exit(0);
	}
	state->data = ch;
	if (!ch && state->sync <= 0) {
		if (state->sync == -4)
			state->sync = 1;
		else
			state->sync--;
	}
	if (state->print_input) {
		printf("%02x (", ch);
		for (i = 0; i < 8; i++)
			printf("%d", (ch >> (7 - i)) & 1);
		printf(")\n");
	}
	return ch;
}

static char in_sync_char(struct state *state)
{
	return state->sync > 0 ? ' ' : '?';
}

static uint32_t next_pc(struct state *state)
{
	uint32_t ret = state->pc;
	if (state->program_flow_only)
		state->branch_count++;
	else
		state->pc += 1 << state->mode;
	return ret;
}

static void print_instruction(struct state *state, bool execute)
{
	int waited = state->wait_count;
	uint32_t pc = next_pc(state);
	if (waited) {
		//printf("  Wait %d\n", state->wait_count);
		state->wait_count = 0;
	}
	if (waited > state->long_wait)
		printf("  ==== Long wait ====\n");
	printf("%c %c(%08x)", in_sync_char(state), execute ? 'E' : 'N', pc);
	if (state->program_flow_only)
		printf(" +%d branch points", state->branch_count);
	if (state->iaddr_valid != 0xffffffff)
		printf(" valid %08x", state->iaddr_valid);
	if (waited)
		printf(" Waited %d", waited);
	printf("\n");
}

static int get_branch_addr(struct state *state)
{
	int addr = state->iaddr >> state->mode;
	int count = 1;
	uint32_t valid_mask = 0x3f;
	uint8_t mask;
	int ret;

	addr = (addr & ~0x3f) | ((state->data >> 1) & 0x3f);
	if (state->print_input)
		printf("  v %x a %x\n", valid_mask << state->mode, addr << state->mode);
	while (state->data & 0x80 && count < 5) {
		get_byte(state);
		if (state->alt_branch && !(state->data & 0x80))
			mask = 0x3f;
		else
			mask = 0x7f;
		addr = (addr & ~(mask << (7 * count - 1))) | ((state->data & mask) << (7 * count - 1));
		valid_mask ^= mask << (7 * count - 1);
		count++;
		if (state->print_input)
			printf("  v %x a %x\n", valid_mask << state->mode, addr << state->mode);
	}
	ret = (count == 5 || (state->alt_branch && count > 1)) && state->data & 0x40;
	if (!ret && state->program_flow_only) {
		// PFT Branch without exception implies an E atom
		print_instruction(state, true);
	}
	if (count == 5) {
		if (!(state->data & 0xb0))
			state->mode = 2;
		else if (!(state->data  & 0xa0))
			state->mode = 1;
		else
			state->mode = 0;
	}
	addr <<= state->mode;
	valid_mask <<= state->mode | ((1 << state->mode) - 1);
	if (state->iaddr_valid < valid_mask)
		state->iaddr_valid = valid_mask;
	state->iaddr = addr;
	state->pc = addr;
	state->branch_count = 0;
	return ret;
}

static int branch(struct state *state)
{
	const char *mode_name[] = { "Jazelle", "Thumb", "ARM" };
	uint32_t exception_data;
	int ret;

	ret = get_branch_addr(state);
	if (ret) {
		exception_data = get_byte(state);
		if (exception_data & 0x80)
			exception_data |= get_byte(state);
	}

	printf("%c   Branch %08x", in_sync_char(state), state->iaddr);
	if (ret)
		printf(" Exception data %04x", exception_data);
	if (state->iaddr_valid != 0xffffffff)
		printf(" (valid %08x)", state->iaddr_valid);
	printf(" %s\n",	mode_name[state->mode]);
	return 0;
}

static int timestamp(struct state *state)
{
	uint64_t timestamp = state->timestamp;
	uint8_t mask = 0x7f;
	int r = !!(state->data & 4);
	int i;

	for (i = 0; i < 9; i++) {
		get_byte(state);
		if (i == 8)
			mask = 0xff;
		timestamp = (timestamp & ~((uint64_t)mask << (7 * i))) | ((uint64_t)(state->data & mask) << (7 * i));
		if (!(state->data & 0x80))
			break;
	}
	// TODO: Convert from gray-code to binary if ETMCCER[28] is not set
	printf("%c   Timestamp %"PRIu64" (%+"PRIi64"), R %d\n",
		in_sync_char(state), timestamp, timestamp - state->timestamp, r);
	state->timestamp = timestamp;
	return 0;
}

static int async(struct state *state)
{
	return 0;
}

static int ignore(struct state *state)
{
	return 0;
}

static int ccount(struct state *state)
{
	uint32_t count = 0;
	int i;
	for (i = 0; i < 5; i++) {
		get_byte(state);
		count |= (state->data & 0x7f) << (7 * i);
		if (!(state->data & 0x80))
			break;
	}
	if (count > state->long_wait)
		printf("    ==== Long wait ====\n");
	printf("%c   Cycle count %d\n", in_sync_char(state), count);
	return 0;
}

static uint32_t get_contextid(struct state *state)
{
	int i;
	uint32_t contextid = 0;
	for (i = 0; i < state->contextid_bytes; i++) {
		get_byte(state);
		contextid |= state->data << (8 * i);
	}
	return contextid;
}

static uint32_t get_addr(struct state *state)
{
	int i;
	uint32_t addr = 0;
	for (i = 0; i < 4; i++) {
		get_byte(state);
		addr |= state->data << (8 * i);
	}
	return addr;
}

static void update_addr(struct state *state, uint8_t ib, uint32_t addr)
{
	if (ib & 0x10) {
		state->mode = 0;
	} else if (addr & 1) {
		state->mode = 1;
		addr &= ~1;
	} else {
		state->mode = 2;
	}
	state->iaddr = addr;
	state->iaddr_valid = 0xffffffff;
	state->pc = addr;
	state->branch_count = 0;
}

static int isync(struct state *state)
{
	uint32_t contextid;
	uint32_t addr;
	uint8_t ib;

	contextid = get_contextid(state);
	ib = get_byte(state);
	addr = get_addr(state);
	update_addr(state, ib, addr);
	printf("%c I-sync Context %08x, IB %02x, Addr %08x\n", in_sync_char(state), contextid, ib, state->iaddr);
	return 0;
}

static int isynccc(struct state *state)
{
	ccount(state);
	return isync(state);
}

static int contextid(struct state *state)
{
	uint32_t contextid;

	contextid = get_contextid(state);
	printf("%c ContextID %08x\n", in_sync_char(state), contextid);
	return 0;
}

static int vmid(struct state *state)
{
	uint8_t vmid;

	vmid = get_byte(state);
	printf("%c VMID %08x\n", in_sync_char(state), vmid);
	return 0;
}

static int ndata(struct state *state)
{
	uint8_t h = state->data;
	int size = (h >> 2) & 3;
	int i;
	static uint32_t daddr = 0;
	uint32_t data = 0;
	if (h & 0x20) {
		for (i = 0; i < 5; i++) {
			get_byte(state);
			daddr = (daddr & ~(0x7f << (7 * i))) | (state->data & 0x7f) << (7 * i);
			if (!(state->data & 0x80))
				break;
		}
	}
	for (i = 0; i < size; i++) {
		get_byte(state);
		data |= state->data << (i * 8);
	}
	if (size) {
		if (h & 0x20)
			printf("%c   Normal data %08x addr %08x\n", in_sync_char(state), data, daddr);
		else
			printf("%c   Normal data %08x\n", in_sync_char(state), data);
	} else {
		if (h & 0x20)
			printf("%c   Normal data addr %08x\n", in_sync_char(state), daddr);
		else
			printf("%c   Normal data\n", in_sync_char(state));
	}
	return 0;
}

static int pheader_cycle_accurate(struct state *state)
{
	int i;
	//printf("  ");
	if (state->data == 0x80) {
		//printf("W");
		state->wait_count++;
	} else if ((state->data & 0xa3) == 0x80) {
		i = (state->data >> 2) & 0x7;
		while (i--) {
			//printf("WE(%08x)", next_pc(state));
			state->wait_count++;
			print_instruction(state, true);
		}
		i = (state->data >> 6) & 0x1;
		while (i--) {
			//printf("WN(%08x)", next_pc(state));
			state->wait_count++;
			print_instruction(state, false);
		}
	} else if ((state->data & 0xf3) == 0x82) {
		//printf("W%c(%08x)%c(%08x)",
		//	(state->data & 0x08) ? 'N' : 'E', next_pc(state),
		//	(state->data & 0x04) ? 'N' : 'E', next_pc(state));
		state->wait_count++;
		print_instruction(state, !(state->data & 0x08));
		print_instruction(state, !(state->data & 0x04));
	} else if ((state->data & 0xa3) == 0xa0) {
		i = ((state->data >> 2) & 0x7) + 1;
		//while (i--)
		//	printf("W");
		state->wait_count += i;
		i = (state->data >> 6) & 0x1;
		while (i--) {
			//printf("E(%08x)", next_pc(state));
			print_instruction(state, true);
		}
	} else if ((state->data & 0xfb) == 0x92) {
		//printf("%c(%08x)", (state->data & 0x04) ? 'N' : 'E', next_pc(state));
		print_instruction(state, !(state->data & 0x04));
	} else {
		state->sync = 0;
		printf("  ?\n");
	}
	//printf("\n");
	return 0;
}

static int pheader_non_cycle_accurate(struct state *state)
{
	int i;
	if ((state->data & 0x83) == 0x80) {
		i = (state->data >> 2) & 0x0f;
		while (i--) {
			//printf("E(%08x)", next_pc(state));
			print_instruction(state, true);
		}
		if (state->data & 0x40) {
			//printf("N(%08x)", next_pc(state));
			print_instruction(state, false);
		}
	} else if ((state->data & 0xf3) == 0x82) {
		//printf("%c(%08x)%c(%08x)",
		//	(state->data & 0x08) ? 'N' : 'E', next_pc(state),
		//	(state->data & 0x04) ? 'N' : 'E', next_pc(state));
		print_instruction(state, !(state->data & 0x08));
		print_instruction(state, !(state->data & 0x04));
	} else {
		state->sync = 0;
		printf("  ?\n");
	}
	return 0;
}

static int pheader(struct state *state)
{
	if (state->cycle_accurate)
		return pheader_cycle_accurate(state);
	else
		return pheader_non_cycle_accurate(state);
}

static int cycle_count_pft(struct state *state)
{
	int i;
	uint8_t h = state->data;
	uint32_t count = (h >> 2) & 0xf;
	int shift = 4;
	if (h & 0x40) {
		for (i = 0; i < 4; i++) {
			get_byte(state);
			count |= (state->data & 0x7f) << shift;
			shift += 7;
			if (!(state->data & 0x80))
				break;
		}
	}
	if (count > state->long_wait)
		printf("    ==== Long wait ====\n");
	printf("%c   Cycle count %d\n", in_sync_char(state), count);
	return 0;
}

static int isync_pft(struct state *state)
{
	uint32_t contextid;
	uint32_t addr;
	uint8_t ib;

	addr = get_addr(state);
	ib = get_byte(state);
	update_addr(state, ib, addr);

	if (state->cycle_accurate && (ib & 0x60)) {
		get_byte(state);
		cycle_count_pft(state);
	}
	
	contextid = get_contextid(state);
	printf("%c I-sync Context %08x, IB %02x, Addr %08x\n", in_sync_char(state), contextid, ib, state->iaddr);
	return 0;
}

static int waypoint(struct state *state)
{
	const char *mode_name[] = { "Jazelle", "Thumb", "ARM" };
	uint8_t ib = 0;
	int ret;

	get_byte(state);
	ret = get_branch_addr(state);
	if (ret)
		ib = get_byte(state);

	printf("%c   Waypoint %08x", in_sync_char(state), state->iaddr);
	if (ret)
		printf(" ib %02x", ib);
	if (state->iaddr_valid != 0xffffffff)
		printf(" (valid %08x)", state->iaddr_valid);
	printf(" %s\n", mode_name[state->mode]);

	return 0;
}

static int branch_pft(struct state *state)
{
	int ret;
	ret = branch(state);
	if (!ret && state->cycle_accurate) {
		get_byte(state);
		ret = cycle_count_pft(state);
	}
	return ret;
}

static int timestamp_pft(struct state *state)
{
	int ret;
	ret = timestamp(state);
	if (!ret && state->cycle_accurate) {
		get_byte(state);
		ret = cycle_count_pft(state);
	}
	return ret;
}

static int atom_cycle_accurate(struct state *state)
{
	uint8_t h = state->data;
	cycle_count_pft(state);
	print_instruction(state, !(h & 0x02));
	return 0;
}

static int atom_non_cycle_accurate(struct state *state)
{
	int i;
	uint8_t d = state->data << 1;
	for (i = 5; i > 0; i--, d <<= 1)
		if (d & 0x80)
			break;
	while (i--) {
		d <<= 1;
		print_instruction(state, !(d & 0x80));
	}
	return 0;
}

static int atom(struct state *state)
{
	if (state->cycle_accurate)
		return atom_cycle_accurate(state);
	else
		return atom_non_cycle_accurate(state);
}

static int trigger(struct state *state)
{
	printf("%c   Trigger\n", in_sync_char(state));
	return 0;
}

static int except_ret(struct state *state)
{
	printf("%c   Exception return\n", in_sync_char(state));
	return 0;
}

struct packet_type packet_types_etm_3_3[] = {
	{ 0x01, 0x01, 0x00, branch,	"Branch address"		},
	{ 0xff, 0x00, 0x00, async,	"A-sync"			},
	{ 0xff, 0x04, 0x00, ccount,	"Cycle count"			},
	{ 0xff, 0x08, 0x00, isync,	"I-sync"			},
	{ 0xff, 0x0c, 0x00, NULL,	"Trigger"			},
	{ 0x93, 0x00, 0x60, NULL,	"Out-of-order data"		},
	{ 0xff, 0x50, 0x00, NULL,	"Store failed"			},
	{ 0xff, 0x70, 0x00, isynccc,	"I-sync with cycle count"	},
	{ 0xd3, 0x50, 0x0c, NULL,	"Out-of-order placeholder"	},
	{ 0xd3, 0x12, 0x00, NULL,	"Reserved"			},
	{ 0xf3, 0x10, 0x00, NULL,	"Reserved"			},
	{ 0xfb, 0x30, 0x00, NULL,	"Reserved"			},
	{ 0xff, 0x3c, 0x00, vmid,	"VMID"				},
	{ 0xff, 0x38, 0x00, NULL,	"Reserved"			},
	{ 0xd3, 0x02, 0x00, ndata,	"Normal data"			},
	{ 0xf3, 0x52, 0x00, NULL,	"Reserved"			},
	{ 0xfb, 0x42, 0x00, timestamp,	"Timestamp"			},
	{ 0xfb, 0x4a, 0x00, NULL,	"Reserved"			},
	{ 0xff, 0x62, 0x00, NULL,	"Data suppressed"		},
	{ 0xff, 0x66, 0x00, ignore,	"Ignore"			},
	{ 0xef, 0x6a, 0x00, NULL,	"Value not traced"		},
	{ 0xff, 0x6e, 0x00, contextid,	"Context ID"			},
	{ 0xff, 0x76, 0x00, NULL,	"Exception exit"		},
	{ 0xff, 0x7e, 0x00, NULL,	"Exception entry"		},
	{ 0xff, 0x72, 0x00, NULL,	"Reserved"			},
	{ 0x81, 0x80, 0x00, pheader,	"P-header"			},

	{ 0x00, 0x00, 0x00, NULL,	"Unknown"			},
};

struct packet_type packet_types_pft[] = {
	{ 0xff, 0x00, 0x00, async,	"A-sync"			},
	{ 0xff, 0x08, 0x00, isync_pft,	"I-sync"			},
	{ 0x81, 0x80, 0x00, atom,	"Atom"				},
	{ 0x01, 0x01, 0x00, branch_pft,	"Branch address"		},
	{ 0xff, 0x72, 0x00, waypoint,	"Waypoint update"		},
	{ 0xff, 0x0c, 0x00, trigger,	"Trigger"			},
	{ 0xff, 0x6e, 0x00, contextid,	"Context ID"			},
	{ 0xff, 0x3c, 0x00, vmid,	"VMID"				},
	{ 0xfb, 0x42, 0x00, timestamp_pft, "Timestamp"			},
	{ 0xff, 0x76, 0x00, except_ret,	"Exception return"		},
	{ 0xff, 0x66, 0x00, ignore,	"Ignore"			},

	{ 0xff, 0x04, 0x00, NULL,	"Reserved"			},
	{ 0x93, 0x00, 0x60, NULL,	"Reserved"			},
	{ 0xff, 0x50, 0x00, NULL,	"Reserved"			},
	{ 0xff, 0x70, 0x00, NULL,	"Reserved"			},
	{ 0xd3, 0x50, 0x0c, NULL,	"Reserved"			},
	{ 0xd3, 0x12, 0x00, NULL,	"Reserved"			},
	{ 0xf3, 0x10, 0x00, NULL,	"Reserved"			},
	{ 0xfb, 0x30, 0x00, NULL,	"Reserved"			},
	{ 0xff, 0x38, 0x00, NULL,	"Reserved"			},
	{ 0xd3, 0x02, 0x00, NULL,	"Reserved"			},
	{ 0xf3, 0x52, 0x00, NULL,	"Reserved"			},
	{ 0xfb, 0x4a, 0x00, NULL,	"Reserved"			},
	{ 0xff, 0x62, 0x00, NULL,	"Reserved"			},
	{ 0xef, 0x6a, 0x00, NULL,	"Reserved"			},
	{ 0xff, 0x7e, 0x00, NULL,	"Reserved"			},

	{ 0x00, 0x00, 0x00, NULL,	"Unknown"			},
};

struct packet_type *packet_types;

int is_match(int i, int ch)
{
	return (ch & packet_types[i].match_mask) == packet_types[i].match_val &&
		(!packet_types[i].nonzero_mask ||
		 (packet_types[i].nonzero_mask & ch));
}

int main(int argc, char **argv)
{
	int ch;
	int i;
	int mc;
	int (*decode)(struct state *state);
	bool print_config = false;
	struct state state;
	int c;
	int option_index = 0;

	enum options {
		OPT_ETM_3_3,
		OPT_ETM_3_4_ALT,
		OPT_PFT_1_1,
		OPT_CYCLE_ACCURATE,
		OPT_CONTEXTID_BYTES,
		OPT_FORMATTER,
		OPT_SOURCEID,
		OPT_LONG_WAIT,
		OPT_PRINT_INPUT,
		OPT_PRINT_CONFIG,
		OPT_PRINT_HELP,
	};

	struct option long_options[] = {
		[OPT_ETM_3_3] = { "etm-3.3", 0, 0, 0 },
		[OPT_ETM_3_4_ALT] ={ "etm-3.4-alt-branch", 0, 0, 0 },
		[OPT_PFT_1_1] = { "pft-1.1", 0, 0, 0 },
		[OPT_CYCLE_ACCURATE] = { "cycle-accurate", 2, &state.cycle_accurate, true },
		[OPT_CONTEXTID_BYTES] = { "contextid-bytes", 1, &state.contextid_bytes, 0 },
		[OPT_FORMATTER] = { "formatter", 2, &state.formatter, true },
		[OPT_SOURCEID] = { "sourceid-match", 1, 0, 0 },
		[OPT_LONG_WAIT] = { "print-long-waits", 1, (int*)&state.long_wait, 0 },
		[OPT_PRINT_INPUT] = { "print-input", 2, &state.print_input, true },
		[OPT_PRINT_CONFIG] = { "print-config", 0, &print_config, true },
		[OPT_PRINT_HELP] = { "help", 0, 0, 'h'},
		{},
	};
	const char *help_txt[] = {
		[OPT_ETM_3_3] = "ETM v3.3 trace data",
		[OPT_ETM_3_4_ALT] = "ETM v3.4 trace data with alternative branch encoding",
		[OPT_PFT_1_1] = "PFT v1.1 trace data\n",

		[OPT_CYCLE_ACCURATE] = "Cycle-accurate tracing was enabled (Default 1)",
		[OPT_CONTEXTID_BYTES] = "Number of Context ID bytes (Default 4)\n",

		[OPT_FORMATTER] = "Enable Formatter Unpacking",
		[OPT_SOURCEID] = "Enable Source ID from formatter. Also enables formatter\n",

		[OPT_LONG_WAIT] = "Highlight long waits",
		[OPT_PRINT_INPUT] = "Print input data",
		[OPT_PRINT_CONFIG] = "Print configuration data",
		[OPT_PRINT_HELP] = "Print usage information",
	};

	memset(&state, 0, sizeof(state));

	state.contextid_bytes = 4;
	state.cycle_accurate = 1;
	state.long_wait = 1000000;

	while (1) {
		c = getopt_long(argc, argv, "h", long_options, &option_index);
		if (c == -1)
			break;

		switch (c) {
		case 0:
			switch (option_index) {
			case OPT_ETM_3_3:
				state.alt_branch = false;
				packet_types = packet_types_etm_3_3;
				break;
			case OPT_ETM_3_4_ALT:
				state.alt_branch = true;
				packet_types = packet_types_etm_3_3;
				break;
			case OPT_PFT_1_1:
				state.alt_branch = true;
				state.program_flow_only = true;
				packet_types = packet_types_pft;
				break;
			case OPT_SOURCEID:
				state.formatter = true;
				state.sourceid_match |= 1 << atoi(optarg);
				break;
			default: {
				int *flag = long_options[option_index].flag;
				if (optarg && flag)
					*flag = atoi(optarg);
				} break;
			};
			if (print_config) {
				printf("option %s", long_options[option_index].name);
				if (optarg)
					printf(" with arg %s", optarg);
				printf("\n");
			}
			break;

		case 'h':
			printf("Usage: %s [options]\n", argv[0]);
			printf("Options:\n");
			for (i = 0; long_options[i].name; i++) {
				printf("  --%-20s %s\n", long_options[i].name, help_txt[i]);
			}
			return 0;

		case '?':
			return 1;

		default:
			printf("unhandled getopt return code %d\n", c);
			return 1;
		}
	}
	if (packet_types == NULL) {
		printf("%s: Must specify etm/pft type\n", argv[0]);
		return 1;
	}
	if (print_config) {
		printf("contextid_bytes %d\n", state.contextid_bytes);
		printf("cycle_accurate %d\n", state.cycle_accurate);
		printf("alt_branch %d\n", state.alt_branch);
		printf("formatter %d\n", state.formatter);
		printf("sourceid_match 0x%x\n", state.sourceid_match);
		printf("print_input %d\n", state.print_input);
		printf("long_wait %d\n", state.long_wait);
	}

	for (ch = 0; ch < 256; ch++) {
		mc = 0;
		for (i = 0; packet_types[i].match_mask; i++)
			if (is_match(i, ch))
				mc++;
		if (mc == 1)
			continue;
		if (mc == 0)
			printf("%02x not covered\n", ch);
		else {
			printf("%02x has multiple matches, %d\n", ch, mc);
			for (i = 0; packet_types[i].match_mask; i++)
				if (is_match(i, ch))
					printf("    %02x %02x %02x %s\n", packet_types[i].match_mask,
					packet_types[i].match_val, packet_types[i].nonzero_mask,
					packet_types[i].name);
		}
	}
	while (1) {
		ch = get_byte(&state);
		for (i = 0; !is_match(i, ch); i++)
			;
		if (state.print_input)
			printf("  %s\n", packet_types[i].name);
		decode = packet_types[i].decode;
		if (decode) {
			decode(&state);
		} else {
			state.sync = 0;
			printf("  %02x: not handled (%s)\n", ch, packet_types[i].name);
		}
	}
	return 0;
}

Attachment: objdump.py
Description: Binary data

Attachment: etm-objdump.py
Description: Binary data

_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to