xref: /aosp_15_r20/external/trace-cmd/lib/trace-cmd/trace-input.c (revision 58e6ee5f017f6a8912852c892d18457e4bafb554)
1*58e6ee5fSAndroid Build Coastguard Worker // SPDX-License-Identifier: LGPL-2.1
2*58e6ee5fSAndroid Build Coastguard Worker /*
3*58e6ee5fSAndroid Build Coastguard Worker  * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <[email protected]>
4*58e6ee5fSAndroid Build Coastguard Worker  *
5*58e6ee5fSAndroid Build Coastguard Worker  */
6*58e6ee5fSAndroid Build Coastguard Worker #define _LARGEFILE64_SOURCE
7*58e6ee5fSAndroid Build Coastguard Worker #include <stdbool.h>
8*58e6ee5fSAndroid Build Coastguard Worker #include <stdio.h>
9*58e6ee5fSAndroid Build Coastguard Worker #include <stdlib.h>
10*58e6ee5fSAndroid Build Coastguard Worker #include <sys/mman.h>
11*58e6ee5fSAndroid Build Coastguard Worker #include <regex.h>
12*58e6ee5fSAndroid Build Coastguard Worker #include <fcntl.h>
13*58e6ee5fSAndroid Build Coastguard Worker #include <unistd.h>
14*58e6ee5fSAndroid Build Coastguard Worker #include <errno.h>
15*58e6ee5fSAndroid Build Coastguard Worker 
16*58e6ee5fSAndroid Build Coastguard Worker #include <linux/time64.h>
17*58e6ee5fSAndroid Build Coastguard Worker 
18*58e6ee5fSAndroid Build Coastguard Worker #include "trace-write-local.h"
19*58e6ee5fSAndroid Build Coastguard Worker #include "trace-cmd-local.h"
20*58e6ee5fSAndroid Build Coastguard Worker #include "trace-local.h"
21*58e6ee5fSAndroid Build Coastguard Worker #include "kbuffer.h"
22*58e6ee5fSAndroid Build Coastguard Worker #include "list.h"
23*58e6ee5fSAndroid Build Coastguard Worker 
24*58e6ee5fSAndroid Build Coastguard Worker #define _STRINGIFY(x) #x
25*58e6ee5fSAndroid Build Coastguard Worker #define STRINGIFY(x) _STRINGIFY(x)
26*58e6ee5fSAndroid Build Coastguard Worker 
27*58e6ee5fSAndroid Build Coastguard Worker #define MISSING_EVENTS (1 << 31)
28*58e6ee5fSAndroid Build Coastguard Worker #define MISSING_STORED (1 << 30)
29*58e6ee5fSAndroid Build Coastguard Worker 
30*58e6ee5fSAndroid Build Coastguard Worker #define COMMIT_MASK ((1 << 27) - 1)
31*58e6ee5fSAndroid Build Coastguard Worker 
32*58e6ee5fSAndroid Build Coastguard Worker /* force uncompressing in memory */
33*58e6ee5fSAndroid Build Coastguard Worker #define INMEMORY_DECOMPRESS
34*58e6ee5fSAndroid Build Coastguard Worker 
35*58e6ee5fSAndroid Build Coastguard Worker /* for debugging read instead of mmap */
36*58e6ee5fSAndroid Build Coastguard Worker static int force_read = 0;
37*58e6ee5fSAndroid Build Coastguard Worker 
38*58e6ee5fSAndroid Build Coastguard Worker struct page_map {
39*58e6ee5fSAndroid Build Coastguard Worker 	struct list_head	list;
40*58e6ee5fSAndroid Build Coastguard Worker 	off64_t			offset;
41*58e6ee5fSAndroid Build Coastguard Worker 	off64_t			size;
42*58e6ee5fSAndroid Build Coastguard Worker 	void			*map;
43*58e6ee5fSAndroid Build Coastguard Worker 	int			ref_count;
44*58e6ee5fSAndroid Build Coastguard Worker };
45*58e6ee5fSAndroid Build Coastguard Worker 
46*58e6ee5fSAndroid Build Coastguard Worker struct page {
47*58e6ee5fSAndroid Build Coastguard Worker 	struct list_head	list;
48*58e6ee5fSAndroid Build Coastguard Worker 	off64_t			offset;
49*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_input	*handle;
50*58e6ee5fSAndroid Build Coastguard Worker 	struct page_map		*page_map;
51*58e6ee5fSAndroid Build Coastguard Worker 	void			*map;
52*58e6ee5fSAndroid Build Coastguard Worker 	int			ref_count;
53*58e6ee5fSAndroid Build Coastguard Worker 	int			cpu;
54*58e6ee5fSAndroid Build Coastguard Worker 	long long		lost_events;
55*58e6ee5fSAndroid Build Coastguard Worker #if DEBUG_RECORD
56*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record	*records;
57*58e6ee5fSAndroid Build Coastguard Worker #endif
58*58e6ee5fSAndroid Build Coastguard Worker };
59*58e6ee5fSAndroid Build Coastguard Worker 
60*58e6ee5fSAndroid Build Coastguard Worker struct zchunk_cache {
61*58e6ee5fSAndroid Build Coastguard Worker 	struct list_head		list;
62*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_compress_chunk *chunk;
63*58e6ee5fSAndroid Build Coastguard Worker 	void				*map;
64*58e6ee5fSAndroid Build Coastguard Worker 	int				ref;
65*58e6ee5fSAndroid Build Coastguard Worker };
66*58e6ee5fSAndroid Build Coastguard Worker 
67*58e6ee5fSAndroid Build Coastguard Worker struct cpu_zdata {
68*58e6ee5fSAndroid Build Coastguard Worker 	/* uncompressed cpu data */
69*58e6ee5fSAndroid Build Coastguard Worker 	int			fd;
70*58e6ee5fSAndroid Build Coastguard Worker #ifdef __ANDROID__
71*58e6ee5fSAndroid Build Coastguard Worker 	char			file[37]; /* strlen(COMPR_TEMP_FILE) */
72*58e6ee5fSAndroid Build Coastguard Worker #else	/* !__ANDROID__ */
73*58e6ee5fSAndroid Build Coastguard Worker 	char			file[26]; /* strlen(COMPR_TEMP_FILE) */
74*58e6ee5fSAndroid Build Coastguard Worker #endif	/* __ANDROID__ */
75*58e6ee5fSAndroid Build Coastguard Worker 
76*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int		count;
77*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int		last_chunk;
78*58e6ee5fSAndroid Build Coastguard Worker 	struct list_head	cache;
79*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_compress_chunk	*chunks;
80*58e6ee5fSAndroid Build Coastguard Worker };
81*58e6ee5fSAndroid Build Coastguard Worker 
82*58e6ee5fSAndroid Build Coastguard Worker #ifdef __ANDROID__
83*58e6ee5fSAndroid Build Coastguard Worker #define COMPR_TEMP_FILE "/data/local/tmp/trace_cpu_dataXXXXXX"
84*58e6ee5fSAndroid Build Coastguard Worker #else	/* !__ANDROID__ */
85*58e6ee5fSAndroid Build Coastguard Worker #define COMPR_TEMP_FILE "/tmp/trace_cpu_dataXXXXXX"
86*58e6ee5fSAndroid Build Coastguard Worker #endif	/* __ANDROID__ */
87*58e6ee5fSAndroid Build Coastguard Worker 
88*58e6ee5fSAndroid Build Coastguard Worker struct cpu_data {
89*58e6ee5fSAndroid Build Coastguard Worker 	/* the first two never change */
90*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	file_offset;
91*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	file_size;
92*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	offset;
93*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	size;
94*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	timestamp;
95*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	first_ts;
96*58e6ee5fSAndroid Build Coastguard Worker 	struct list_head	page_maps;
97*58e6ee5fSAndroid Build Coastguard Worker 	struct page_map		*page_map;
98*58e6ee5fSAndroid Build Coastguard Worker 	struct page		**pages;
99*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record	*next;
100*58e6ee5fSAndroid Build Coastguard Worker 	struct page		*page;
101*58e6ee5fSAndroid Build Coastguard Worker 	struct kbuffer		*kbuf;
102*58e6ee5fSAndroid Build Coastguard Worker 	int			nr_pages;
103*58e6ee5fSAndroid Build Coastguard Worker 	int			page_cnt;
104*58e6ee5fSAndroid Build Coastguard Worker 	int			cpu;
105*58e6ee5fSAndroid Build Coastguard Worker 	int			pipe_fd;
106*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_zdata	compress;
107*58e6ee5fSAndroid Build Coastguard Worker };
108*58e6ee5fSAndroid Build Coastguard Worker 
109*58e6ee5fSAndroid Build Coastguard Worker struct cpu_file_data {
110*58e6ee5fSAndroid Build Coastguard Worker 	int			cpu;
111*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	offset;
112*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	size;
113*58e6ee5fSAndroid Build Coastguard Worker };
114*58e6ee5fSAndroid Build Coastguard Worker 
115*58e6ee5fSAndroid Build Coastguard Worker struct input_buffer_instance {
116*58e6ee5fSAndroid Build Coastguard Worker 	char			*name;
117*58e6ee5fSAndroid Build Coastguard Worker 	size_t			offset;
118*58e6ee5fSAndroid Build Coastguard Worker 	char			*clock;
119*58e6ee5fSAndroid Build Coastguard Worker 	bool			latency;
120*58e6ee5fSAndroid Build Coastguard Worker 	int			page_size;
121*58e6ee5fSAndroid Build Coastguard Worker 	int			cpus;
122*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_file_data	*cpu_data;
123*58e6ee5fSAndroid Build Coastguard Worker };
124*58e6ee5fSAndroid Build Coastguard Worker 
125*58e6ee5fSAndroid Build Coastguard Worker struct ts_offset_sample {
126*58e6ee5fSAndroid Build Coastguard Worker 	long long	time;
127*58e6ee5fSAndroid Build Coastguard Worker 	long long	offset;
128*58e6ee5fSAndroid Build Coastguard Worker 	long long	scaling;
129*58e6ee5fSAndroid Build Coastguard Worker 	long long	fraction;
130*58e6ee5fSAndroid Build Coastguard Worker };
131*58e6ee5fSAndroid Build Coastguard Worker 
132*58e6ee5fSAndroid Build Coastguard Worker struct guest_trace_info {
133*58e6ee5fSAndroid Build Coastguard Worker 	struct guest_trace_info	*next;
134*58e6ee5fSAndroid Build Coastguard Worker 	char			*name;
135*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	trace_id;
136*58e6ee5fSAndroid Build Coastguard Worker 	int			vcpu_count;
137*58e6ee5fSAndroid Build Coastguard Worker 	int			*cpu_pid;
138*58e6ee5fSAndroid Build Coastguard Worker };
139*58e6ee5fSAndroid Build Coastguard Worker 
140*58e6ee5fSAndroid Build Coastguard Worker struct timesync_offsets {
141*58e6ee5fSAndroid Build Coastguard Worker 	int	ts_samples_count;
142*58e6ee5fSAndroid Build Coastguard Worker 	struct ts_offset_sample	*ts_samples;
143*58e6ee5fSAndroid Build Coastguard Worker };
144*58e6ee5fSAndroid Build Coastguard Worker 
145*58e6ee5fSAndroid Build Coastguard Worker struct host_trace_info {
146*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	peer_trace_id;
147*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int		flags;
148*58e6ee5fSAndroid Build Coastguard Worker 	bool			sync_enable;
149*58e6ee5fSAndroid Build Coastguard Worker 	int			ts_samples_count;
150*58e6ee5fSAndroid Build Coastguard Worker 	struct ts_offset_sample	*ts_samples;
151*58e6ee5fSAndroid Build Coastguard Worker 	int			cpu_count;
152*58e6ee5fSAndroid Build Coastguard Worker 	struct timesync_offsets	*ts_offsets;
153*58e6ee5fSAndroid Build Coastguard Worker };
154*58e6ee5fSAndroid Build Coastguard Worker 
155*58e6ee5fSAndroid Build Coastguard Worker struct tsc2nsec {
156*58e6ee5fSAndroid Build Coastguard Worker 	int	mult;
157*58e6ee5fSAndroid Build Coastguard Worker 	int	shift;
158*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset;
159*58e6ee5fSAndroid Build Coastguard Worker };
160*58e6ee5fSAndroid Build Coastguard Worker 
161*58e6ee5fSAndroid Build Coastguard Worker struct file_section {
162*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long		section_offset;
163*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long		data_offset;
164*58e6ee5fSAndroid Build Coastguard Worker 	int				id;
165*58e6ee5fSAndroid Build Coastguard Worker 	int				flags;
166*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section		*next;
167*58e6ee5fSAndroid Build Coastguard Worker };
168*58e6ee5fSAndroid Build Coastguard Worker 
169*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_input {
170*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle	*pevent;
171*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_plugin_list	*plugin_list;
172*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_input	*parent;
173*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long		file_state;
174*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	trace_id;
175*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	next_offset;
176*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long		flags;
177*58e6ee5fSAndroid Build Coastguard Worker 	int			fd;
178*58e6ee5fSAndroid Build Coastguard Worker 	int			long_size;
179*58e6ee5fSAndroid Build Coastguard Worker 	int			page_size;
180*58e6ee5fSAndroid Build Coastguard Worker 	int			page_map_size;
181*58e6ee5fSAndroid Build Coastguard Worker 	int			max_cpu;
182*58e6ee5fSAndroid Build Coastguard Worker 	int			cpus;
183*58e6ee5fSAndroid Build Coastguard Worker 	int			ref;
184*58e6ee5fSAndroid Build Coastguard Worker 	int			nr_buffers;	/* buffer instances */
185*58e6ee5fSAndroid Build Coastguard Worker 	bool			use_trace_clock;
186*58e6ee5fSAndroid Build Coastguard Worker 	bool			read_page;
187*58e6ee5fSAndroid Build Coastguard Worker 	bool			use_pipe;
188*58e6ee5fSAndroid Build Coastguard Worker 	bool			read_zpage; /* uncompress pages in memory, do not use tmp files */
189*58e6ee5fSAndroid Build Coastguard Worker 	bool			cpu_compressed;
190*58e6ee5fSAndroid Build Coastguard Worker 	int			file_version;
191*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int		cpustats_size;
192*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_zdata	latz;
193*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data 	*cpu_data;
194*58e6ee5fSAndroid Build Coastguard Worker 	long long		ts_offset;
195*58e6ee5fSAndroid Build Coastguard Worker 	struct tsc2nsec		tsc_calc;
196*58e6ee5fSAndroid Build Coastguard Worker 
197*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int		strings_size;	/* size of the metadata strings */
198*58e6ee5fSAndroid Build Coastguard Worker 	char			*strings;	/* metadata strings */
199*58e6ee5fSAndroid Build Coastguard Worker 
200*58e6ee5fSAndroid Build Coastguard Worker 	bool			read_compress;
201*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_compression *compress;
202*58e6ee5fSAndroid Build Coastguard Worker 
203*58e6ee5fSAndroid Build Coastguard Worker 	struct host_trace_info	host;
204*58e6ee5fSAndroid Build Coastguard Worker 	double			ts2secs;
205*58e6ee5fSAndroid Build Coastguard Worker 	char *			cpustats;
206*58e6ee5fSAndroid Build Coastguard Worker 	char *			uname;
207*58e6ee5fSAndroid Build Coastguard Worker 	char *			version;
208*58e6ee5fSAndroid Build Coastguard Worker 	char *			trace_clock;
209*58e6ee5fSAndroid Build Coastguard Worker 	struct input_buffer_instance	top_buffer;
210*58e6ee5fSAndroid Build Coastguard Worker 	struct input_buffer_instance	*buffers;
211*58e6ee5fSAndroid Build Coastguard Worker 	int			parsing_failures;
212*58e6ee5fSAndroid Build Coastguard Worker 	struct guest_trace_info	*guest;
213*58e6ee5fSAndroid Build Coastguard Worker 
214*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_ftrace	finfo;
215*58e6ee5fSAndroid Build Coastguard Worker 
216*58e6ee5fSAndroid Build Coastguard Worker 	struct hook_list	*hooks;
217*58e6ee5fSAndroid Build Coastguard Worker 	struct pid_addr_maps	*pid_maps;
218*58e6ee5fSAndroid Build Coastguard Worker 	/* file information */
219*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section	*sections;
220*58e6ee5fSAndroid Build Coastguard Worker 	bool			options_init;
221*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	options_start;
222*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	options_last_offset;
223*58e6ee5fSAndroid Build Coastguard Worker 	size_t			total_file_size;
224*58e6ee5fSAndroid Build Coastguard Worker 
225*58e6ee5fSAndroid Build Coastguard Worker 	/* For custom profilers. */
226*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_show_data_func	show_data_func;
227*58e6ee5fSAndroid Build Coastguard Worker };
228*58e6ee5fSAndroid Build Coastguard Worker 
229*58e6ee5fSAndroid Build Coastguard Worker __thread struct tracecmd_input *tracecmd_curr_thread_handle;
230*58e6ee5fSAndroid Build Coastguard Worker 
231*58e6ee5fSAndroid Build Coastguard Worker #define CHECK_READ_STATE(H, S) ((H)->file_version < FILE_VERSION_SECTIONS && (H)->file_state >= (S))
232*58e6ee5fSAndroid Build Coastguard Worker #define HAS_SECTIONS(H) ((H)->flags & TRACECMD_FL_SECTIONED)
233*58e6ee5fSAndroid Build Coastguard Worker #define HAS_COMPRESSION(H) ((H)->flags & TRACECMD_FL_COMPRESSION)
234*58e6ee5fSAndroid Build Coastguard Worker 
235*58e6ee5fSAndroid Build Coastguard Worker static int read_options_type(struct tracecmd_input *handle);
236*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_set_flag(struct tracecmd_input * handle,int flag)237*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_set_flag(struct tracecmd_input *handle, int flag)
238*58e6ee5fSAndroid Build Coastguard Worker {
239*58e6ee5fSAndroid Build Coastguard Worker 	handle->flags |= flag;
240*58e6ee5fSAndroid Build Coastguard Worker }
241*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_clear_flag(struct tracecmd_input * handle,int flag)242*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_clear_flag(struct tracecmd_input *handle, int flag)
243*58e6ee5fSAndroid Build Coastguard Worker {
244*58e6ee5fSAndroid Build Coastguard Worker 	handle->flags &= ~flag;
245*58e6ee5fSAndroid Build Coastguard Worker }
246*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_get_flags(struct tracecmd_input * handle)247*58e6ee5fSAndroid Build Coastguard Worker unsigned long tracecmd_get_flags(struct tracecmd_input *handle)
248*58e6ee5fSAndroid Build Coastguard Worker {
249*58e6ee5fSAndroid Build Coastguard Worker 	return handle->flags;
250*58e6ee5fSAndroid Build Coastguard Worker }
251*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_get_file_state(struct tracecmd_input * handle)252*58e6ee5fSAndroid Build Coastguard Worker enum tracecmd_file_states tracecmd_get_file_state(struct tracecmd_input *handle)
253*58e6ee5fSAndroid Build Coastguard Worker {
254*58e6ee5fSAndroid Build Coastguard Worker 	return handle->file_state;
255*58e6ee5fSAndroid Build Coastguard Worker }
256*58e6ee5fSAndroid Build Coastguard Worker 
257*58e6ee5fSAndroid Build Coastguard Worker #if DEBUG_RECORD
remove_record(struct page * page,struct tep_record * record)258*58e6ee5fSAndroid Build Coastguard Worker static void remove_record(struct page *page, struct tep_record *record)
259*58e6ee5fSAndroid Build Coastguard Worker {
260*58e6ee5fSAndroid Build Coastguard Worker 	if (record->prev)
261*58e6ee5fSAndroid Build Coastguard Worker 		record->prev->next = record->next;
262*58e6ee5fSAndroid Build Coastguard Worker 	else
263*58e6ee5fSAndroid Build Coastguard Worker 		page->records = record->next;
264*58e6ee5fSAndroid Build Coastguard Worker 	if (record->next)
265*58e6ee5fSAndroid Build Coastguard Worker 		record->next->prev = record->prev;
266*58e6ee5fSAndroid Build Coastguard Worker }
add_record(struct page * page,struct tep_record * record)267*58e6ee5fSAndroid Build Coastguard Worker static void add_record(struct page *page, struct tep_record *record)
268*58e6ee5fSAndroid Build Coastguard Worker {
269*58e6ee5fSAndroid Build Coastguard Worker 	if (page->records)
270*58e6ee5fSAndroid Build Coastguard Worker 		page->records->prev = record;
271*58e6ee5fSAndroid Build Coastguard Worker 	record->next = page->records;
272*58e6ee5fSAndroid Build Coastguard Worker 	record->prev = NULL;
273*58e6ee5fSAndroid Build Coastguard Worker 	page->records = record;
274*58e6ee5fSAndroid Build Coastguard Worker }
show_records(struct page ** pages,int nr_pages)275*58e6ee5fSAndroid Build Coastguard Worker static const char *show_records(struct page **pages, int nr_pages)
276*58e6ee5fSAndroid Build Coastguard Worker {
277*58e6ee5fSAndroid Build Coastguard Worker 	static char buf[BUFSIZ + 1];
278*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record;
279*58e6ee5fSAndroid Build Coastguard Worker 	struct page *page;
280*58e6ee5fSAndroid Build Coastguard Worker 	int len;
281*58e6ee5fSAndroid Build Coastguard Worker 	int i;
282*58e6ee5fSAndroid Build Coastguard Worker 
283*58e6ee5fSAndroid Build Coastguard Worker 	memset(buf, 0, sizeof(buf));
284*58e6ee5fSAndroid Build Coastguard Worker 	len = 0;
285*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_pages; i++) {
286*58e6ee5fSAndroid Build Coastguard Worker 		page = pages[i];
287*58e6ee5fSAndroid Build Coastguard Worker 		if (!page)
288*58e6ee5fSAndroid Build Coastguard Worker 			continue;
289*58e6ee5fSAndroid Build Coastguard Worker 		for (record = page->records; record; record = record->next) {
290*58e6ee5fSAndroid Build Coastguard Worker 			int n;
291*58e6ee5fSAndroid Build Coastguard Worker 			n = snprintf(buf+len, BUFSIZ - len, " 0x%lx", record->alloc_addr);
292*58e6ee5fSAndroid Build Coastguard Worker 			len += n;
293*58e6ee5fSAndroid Build Coastguard Worker 			if (len >= BUFSIZ)
294*58e6ee5fSAndroid Build Coastguard Worker 				break;
295*58e6ee5fSAndroid Build Coastguard Worker 		}
296*58e6ee5fSAndroid Build Coastguard Worker 	}
297*58e6ee5fSAndroid Build Coastguard Worker 	return buf;
298*58e6ee5fSAndroid Build Coastguard Worker }
299*58e6ee5fSAndroid Build Coastguard Worker #else
remove_record(struct page * page,struct tep_record * record)300*58e6ee5fSAndroid Build Coastguard Worker static inline void remove_record(struct page *page, struct tep_record *record) {}
add_record(struct page * page,struct tep_record * record)301*58e6ee5fSAndroid Build Coastguard Worker static inline void add_record(struct page *page, struct tep_record *record) {}
show_records(struct page ** pages,int nr_pages)302*58e6ee5fSAndroid Build Coastguard Worker static const char *show_records(struct page **pages, int nr_pages)
303*58e6ee5fSAndroid Build Coastguard Worker {
304*58e6ee5fSAndroid Build Coastguard Worker 	return "";
305*58e6ee5fSAndroid Build Coastguard Worker }
306*58e6ee5fSAndroid Build Coastguard Worker #endif
307*58e6ee5fSAndroid Build Coastguard Worker 
308*58e6ee5fSAndroid Build Coastguard Worker static int init_cpu(struct tracecmd_input *handle, int cpu);
309*58e6ee5fSAndroid Build Coastguard Worker 
do_read_fd(int fd,void * data,size_t size)310*58e6ee5fSAndroid Build Coastguard Worker static ssize_t do_read_fd(int fd, void *data, size_t size)
311*58e6ee5fSAndroid Build Coastguard Worker {
312*58e6ee5fSAndroid Build Coastguard Worker 	ssize_t tot = 0;
313*58e6ee5fSAndroid Build Coastguard Worker 	ssize_t r;
314*58e6ee5fSAndroid Build Coastguard Worker 
315*58e6ee5fSAndroid Build Coastguard Worker 	do {
316*58e6ee5fSAndroid Build Coastguard Worker 		r = read(fd, data + tot, size - tot);
317*58e6ee5fSAndroid Build Coastguard Worker 		tot += r;
318*58e6ee5fSAndroid Build Coastguard Worker 
319*58e6ee5fSAndroid Build Coastguard Worker 		if (!r)
320*58e6ee5fSAndroid Build Coastguard Worker 			break;
321*58e6ee5fSAndroid Build Coastguard Worker 		if (r < 0)
322*58e6ee5fSAndroid Build Coastguard Worker 			return r;
323*58e6ee5fSAndroid Build Coastguard Worker 	} while (tot != size);
324*58e6ee5fSAndroid Build Coastguard Worker 
325*58e6ee5fSAndroid Build Coastguard Worker 	return tot;
326*58e6ee5fSAndroid Build Coastguard Worker }
327*58e6ee5fSAndroid Build Coastguard Worker 
do_lseek(struct tracecmd_input * handle,int offset,int whence)328*58e6ee5fSAndroid Build Coastguard Worker static inline int do_lseek(struct tracecmd_input *handle, int offset, int whence)
329*58e6ee5fSAndroid Build Coastguard Worker {
330*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->read_compress)
331*58e6ee5fSAndroid Build Coastguard Worker 		return tracecmd_compress_lseek(handle->compress, offset, whence);
332*58e6ee5fSAndroid Build Coastguard Worker 	else
333*58e6ee5fSAndroid Build Coastguard Worker 		return lseek(handle->fd, offset, whence);
334*58e6ee5fSAndroid Build Coastguard Worker }
335*58e6ee5fSAndroid Build Coastguard Worker 
do_read(struct tracecmd_input * handle,void * data,size_t size)336*58e6ee5fSAndroid Build Coastguard Worker static inline ssize_t do_read(struct tracecmd_input *handle, void *data, size_t size)
337*58e6ee5fSAndroid Build Coastguard Worker {
338*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->read_compress)
339*58e6ee5fSAndroid Build Coastguard Worker 		return tracecmd_compress_buffer_read(handle->compress, data, size);
340*58e6ee5fSAndroid Build Coastguard Worker 	else
341*58e6ee5fSAndroid Build Coastguard Worker 		return do_read_fd(handle->fd, data, size);
342*58e6ee5fSAndroid Build Coastguard Worker }
343*58e6ee5fSAndroid Build Coastguard Worker 
344*58e6ee5fSAndroid Build Coastguard Worker static ssize_t
do_read_check(struct tracecmd_input * handle,void * data,size_t size)345*58e6ee5fSAndroid Build Coastguard Worker do_read_check(struct tracecmd_input *handle, void *data, size_t size)
346*58e6ee5fSAndroid Build Coastguard Worker {
347*58e6ee5fSAndroid Build Coastguard Worker 	ssize_t ret;
348*58e6ee5fSAndroid Build Coastguard Worker 
349*58e6ee5fSAndroid Build Coastguard Worker 	ret = do_read(handle, data, size);
350*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
351*58e6ee5fSAndroid Build Coastguard Worker 		return ret;
352*58e6ee5fSAndroid Build Coastguard Worker 	if (ret != size)
353*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
354*58e6ee5fSAndroid Build Coastguard Worker 
355*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
356*58e6ee5fSAndroid Build Coastguard Worker }
357*58e6ee5fSAndroid Build Coastguard Worker 
read_string(struct tracecmd_input * handle)358*58e6ee5fSAndroid Build Coastguard Worker static char *read_string(struct tracecmd_input *handle)
359*58e6ee5fSAndroid Build Coastguard Worker {
360*58e6ee5fSAndroid Build Coastguard Worker 	char buf[BUFSIZ];
361*58e6ee5fSAndroid Build Coastguard Worker 	char *str = NULL;
362*58e6ee5fSAndroid Build Coastguard Worker 	size_t size = 0;
363*58e6ee5fSAndroid Build Coastguard Worker 	ssize_t i;
364*58e6ee5fSAndroid Build Coastguard Worker 	ssize_t r;
365*58e6ee5fSAndroid Build Coastguard Worker 
366*58e6ee5fSAndroid Build Coastguard Worker 	for (;;) {
367*58e6ee5fSAndroid Build Coastguard Worker 		r = do_read(handle, buf, BUFSIZ);
368*58e6ee5fSAndroid Build Coastguard Worker 		if (r <= 0)
369*58e6ee5fSAndroid Build Coastguard Worker 			goto fail;
370*58e6ee5fSAndroid Build Coastguard Worker 
371*58e6ee5fSAndroid Build Coastguard Worker 		for (i = 0; i < r; i++) {
372*58e6ee5fSAndroid Build Coastguard Worker 			if (!buf[i])
373*58e6ee5fSAndroid Build Coastguard Worker 				break;
374*58e6ee5fSAndroid Build Coastguard Worker 		}
375*58e6ee5fSAndroid Build Coastguard Worker 		if (i < r)
376*58e6ee5fSAndroid Build Coastguard Worker 			break;
377*58e6ee5fSAndroid Build Coastguard Worker 
378*58e6ee5fSAndroid Build Coastguard Worker 		if (str) {
379*58e6ee5fSAndroid Build Coastguard Worker 			size += BUFSIZ;
380*58e6ee5fSAndroid Build Coastguard Worker 			str = realloc(str, size);
381*58e6ee5fSAndroid Build Coastguard Worker 			if (!str)
382*58e6ee5fSAndroid Build Coastguard Worker 				return NULL;
383*58e6ee5fSAndroid Build Coastguard Worker 			memcpy(str + (size - BUFSIZ), buf, BUFSIZ);
384*58e6ee5fSAndroid Build Coastguard Worker 		} else {
385*58e6ee5fSAndroid Build Coastguard Worker 			size = BUFSIZ;
386*58e6ee5fSAndroid Build Coastguard Worker 			str = malloc(size);
387*58e6ee5fSAndroid Build Coastguard Worker 			if (!str)
388*58e6ee5fSAndroid Build Coastguard Worker 				return NULL;
389*58e6ee5fSAndroid Build Coastguard Worker 			memcpy(str, buf, size);
390*58e6ee5fSAndroid Build Coastguard Worker 		}
391*58e6ee5fSAndroid Build Coastguard Worker 	}
392*58e6ee5fSAndroid Build Coastguard Worker 
393*58e6ee5fSAndroid Build Coastguard Worker 	/* move the file descriptor to the end of the string */
394*58e6ee5fSAndroid Build Coastguard Worker 	r = do_lseek(handle, -(r - (i+1)), SEEK_CUR);
395*58e6ee5fSAndroid Build Coastguard Worker 	if (r < 0)
396*58e6ee5fSAndroid Build Coastguard Worker 		goto fail;
397*58e6ee5fSAndroid Build Coastguard Worker 
398*58e6ee5fSAndroid Build Coastguard Worker 	if (str) {
399*58e6ee5fSAndroid Build Coastguard Worker 		size += i + 1;
400*58e6ee5fSAndroid Build Coastguard Worker 		str = realloc(str, size);
401*58e6ee5fSAndroid Build Coastguard Worker 		if (!str)
402*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
403*58e6ee5fSAndroid Build Coastguard Worker 		memcpy(str + (size - i), buf, i);
404*58e6ee5fSAndroid Build Coastguard Worker 		str[size] = 0;
405*58e6ee5fSAndroid Build Coastguard Worker 	} else {
406*58e6ee5fSAndroid Build Coastguard Worker 		size = i + 1;
407*58e6ee5fSAndroid Build Coastguard Worker 		str = malloc(size);
408*58e6ee5fSAndroid Build Coastguard Worker 		if (!str)
409*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
410*58e6ee5fSAndroid Build Coastguard Worker 		memcpy(str, buf, i);
411*58e6ee5fSAndroid Build Coastguard Worker 		str[i] = 0;
412*58e6ee5fSAndroid Build Coastguard Worker 	}
413*58e6ee5fSAndroid Build Coastguard Worker 
414*58e6ee5fSAndroid Build Coastguard Worker 	return str;
415*58e6ee5fSAndroid Build Coastguard Worker 
416*58e6ee5fSAndroid Build Coastguard Worker  fail:
417*58e6ee5fSAndroid Build Coastguard Worker 	if (str)
418*58e6ee5fSAndroid Build Coastguard Worker 		free(str);
419*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
420*58e6ee5fSAndroid Build Coastguard Worker }
421*58e6ee5fSAndroid Build Coastguard Worker 
read2(struct tracecmd_input * handle,unsigned short * size)422*58e6ee5fSAndroid Build Coastguard Worker static int read2(struct tracecmd_input *handle, unsigned short *size)
423*58e6ee5fSAndroid Build Coastguard Worker {
424*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = handle->pevent;
425*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short data;
426*58e6ee5fSAndroid Build Coastguard Worker 
427*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, &data, 2))
428*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
429*58e6ee5fSAndroid Build Coastguard Worker 
430*58e6ee5fSAndroid Build Coastguard Worker 	*size = tep_read_number(pevent, &data, 2);
431*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
432*58e6ee5fSAndroid Build Coastguard Worker }
433*58e6ee5fSAndroid Build Coastguard Worker 
read4(struct tracecmd_input * handle,unsigned int * size)434*58e6ee5fSAndroid Build Coastguard Worker static int read4(struct tracecmd_input *handle, unsigned int *size)
435*58e6ee5fSAndroid Build Coastguard Worker {
436*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = handle->pevent;
437*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int data;
438*58e6ee5fSAndroid Build Coastguard Worker 
439*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, &data, 4))
440*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
441*58e6ee5fSAndroid Build Coastguard Worker 
442*58e6ee5fSAndroid Build Coastguard Worker 	*size = tep_read_number(pevent, &data, 4);
443*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
444*58e6ee5fSAndroid Build Coastguard Worker }
445*58e6ee5fSAndroid Build Coastguard Worker 
read8(struct tracecmd_input * handle,unsigned long long * size)446*58e6ee5fSAndroid Build Coastguard Worker static int read8(struct tracecmd_input *handle, unsigned long long *size)
447*58e6ee5fSAndroid Build Coastguard Worker {
448*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = handle->pevent;
449*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long data;
450*58e6ee5fSAndroid Build Coastguard Worker 
451*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, &data, 8))
452*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
453*58e6ee5fSAndroid Build Coastguard Worker 
454*58e6ee5fSAndroid Build Coastguard Worker 	*size = tep_read_number(pevent, &data, 8);
455*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
456*58e6ee5fSAndroid Build Coastguard Worker }
457*58e6ee5fSAndroid Build Coastguard Worker 
in_uncompress_reset(struct tracecmd_input * handle)458*58e6ee5fSAndroid Build Coastguard Worker __hidden void in_uncompress_reset(struct tracecmd_input *handle)
459*58e6ee5fSAndroid Build Coastguard Worker {
460*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->compress) {
461*58e6ee5fSAndroid Build Coastguard Worker 		handle->read_compress = false;
462*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_compress_reset(handle->compress);
463*58e6ee5fSAndroid Build Coastguard Worker 	}
464*58e6ee5fSAndroid Build Coastguard Worker }
465*58e6ee5fSAndroid Build Coastguard Worker 
in_uncompress_block(struct tracecmd_input * handle)466*58e6ee5fSAndroid Build Coastguard Worker __hidden int in_uncompress_block(struct tracecmd_input *handle)
467*58e6ee5fSAndroid Build Coastguard Worker {
468*58e6ee5fSAndroid Build Coastguard Worker 	int ret = 0;
469*58e6ee5fSAndroid Build Coastguard Worker 
470*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->compress) {
471*58e6ee5fSAndroid Build Coastguard Worker 		ret = tracecmd_uncompress_block(handle->compress);
472*58e6ee5fSAndroid Build Coastguard Worker 		if (!ret)
473*58e6ee5fSAndroid Build Coastguard Worker 			handle->read_compress = true;
474*58e6ee5fSAndroid Build Coastguard Worker 	}
475*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
476*58e6ee5fSAndroid Build Coastguard Worker }
477*58e6ee5fSAndroid Build Coastguard Worker 
section_get(struct tracecmd_input * handle,int id)478*58e6ee5fSAndroid Build Coastguard Worker static struct file_section *section_get(struct tracecmd_input *handle, int id)
479*58e6ee5fSAndroid Build Coastguard Worker {
480*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *sec;
481*58e6ee5fSAndroid Build Coastguard Worker 
482*58e6ee5fSAndroid Build Coastguard Worker 	for (sec = handle->sections; sec; sec = sec->next) {
483*58e6ee5fSAndroid Build Coastguard Worker 		if (sec->id == id)
484*58e6ee5fSAndroid Build Coastguard Worker 			return sec;
485*58e6ee5fSAndroid Build Coastguard Worker 	}
486*58e6ee5fSAndroid Build Coastguard Worker 
487*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
488*58e6ee5fSAndroid Build Coastguard Worker }
489*58e6ee5fSAndroid Build Coastguard Worker 
section_open(struct tracecmd_input * handle,int id)490*58e6ee5fSAndroid Build Coastguard Worker static struct file_section *section_open(struct tracecmd_input *handle, int id)
491*58e6ee5fSAndroid Build Coastguard Worker {
492*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *sec = section_get(handle, id);
493*58e6ee5fSAndroid Build Coastguard Worker 
494*58e6ee5fSAndroid Build Coastguard Worker 	if (!sec)
495*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
496*58e6ee5fSAndroid Build Coastguard Worker 
497*58e6ee5fSAndroid Build Coastguard Worker 	if (lseek64(handle->fd, sec->data_offset, SEEK_SET) == (off64_t)-1)
498*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
499*58e6ee5fSAndroid Build Coastguard Worker 
500*58e6ee5fSAndroid Build Coastguard Worker 	if ((sec->flags & TRACECMD_SEC_FL_COMPRESS) && in_uncompress_block(handle))
501*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
502*58e6ee5fSAndroid Build Coastguard Worker 
503*58e6ee5fSAndroid Build Coastguard Worker 	return sec;
504*58e6ee5fSAndroid Build Coastguard Worker }
505*58e6ee5fSAndroid Build Coastguard Worker 
section_close(struct tracecmd_input * handle,struct file_section * sec)506*58e6ee5fSAndroid Build Coastguard Worker static void section_close(struct tracecmd_input *handle, struct file_section *sec)
507*58e6ee5fSAndroid Build Coastguard Worker {
508*58e6ee5fSAndroid Build Coastguard Worker 	if (sec->flags & TRACECMD_SEC_FL_COMPRESS)
509*58e6ee5fSAndroid Build Coastguard Worker 		in_uncompress_reset(handle);
510*58e6ee5fSAndroid Build Coastguard Worker }
511*58e6ee5fSAndroid Build Coastguard Worker 
section_add_or_update(struct tracecmd_input * handle,int id,int flags,unsigned long long section_offset,unsigned long long data_offset)512*58e6ee5fSAndroid Build Coastguard Worker static int section_add_or_update(struct tracecmd_input *handle, int id, int flags,
513*58e6ee5fSAndroid Build Coastguard Worker 				 unsigned long long section_offset,
514*58e6ee5fSAndroid Build Coastguard Worker 				 unsigned long long data_offset)
515*58e6ee5fSAndroid Build Coastguard Worker {
516*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *sec = section_get(handle, id);
517*58e6ee5fSAndroid Build Coastguard Worker 
518*58e6ee5fSAndroid Build Coastguard Worker 	if (!sec) {
519*58e6ee5fSAndroid Build Coastguard Worker 		sec = calloc(1, sizeof(struct file_section));
520*58e6ee5fSAndroid Build Coastguard Worker 		if (!sec)
521*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
522*58e6ee5fSAndroid Build Coastguard Worker 		sec->next = handle->sections;
523*58e6ee5fSAndroid Build Coastguard Worker 		handle->sections = sec;
524*58e6ee5fSAndroid Build Coastguard Worker 		sec->id = id;
525*58e6ee5fSAndroid Build Coastguard Worker 	}
526*58e6ee5fSAndroid Build Coastguard Worker 
527*58e6ee5fSAndroid Build Coastguard Worker 	if (section_offset)
528*58e6ee5fSAndroid Build Coastguard Worker 		sec->section_offset = section_offset;
529*58e6ee5fSAndroid Build Coastguard Worker 	if (data_offset)
530*58e6ee5fSAndroid Build Coastguard Worker 		sec->data_offset = data_offset;
531*58e6ee5fSAndroid Build Coastguard Worker 	if (flags >= 0)
532*58e6ee5fSAndroid Build Coastguard Worker 		sec->flags = flags;
533*58e6ee5fSAndroid Build Coastguard Worker 
534*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
535*58e6ee5fSAndroid Build Coastguard Worker }
536*58e6ee5fSAndroid Build Coastguard Worker 
read_header_files(struct tracecmd_input * handle)537*58e6ee5fSAndroid Build Coastguard Worker static int read_header_files(struct tracecmd_input *handle)
538*58e6ee5fSAndroid Build Coastguard Worker {
539*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = handle->pevent;
540*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
541*58e6ee5fSAndroid Build Coastguard Worker 	char *header;
542*58e6ee5fSAndroid Build Coastguard Worker 	char buf[BUFSIZ];
543*58e6ee5fSAndroid Build Coastguard Worker 
544*58e6ee5fSAndroid Build Coastguard Worker 	if (CHECK_READ_STATE(handle, TRACECMD_FILE_HEADERS))
545*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
546*58e6ee5fSAndroid Build Coastguard Worker 
547*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle))
548*58e6ee5fSAndroid Build Coastguard Worker 		section_add_or_update(handle, TRACECMD_OPTION_HEADER_INFO, 0, 0,
549*58e6ee5fSAndroid Build Coastguard Worker 				      lseek64(handle->fd, 0, SEEK_CUR));
550*58e6ee5fSAndroid Build Coastguard Worker 
551*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, buf, 12))
552*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
553*58e6ee5fSAndroid Build Coastguard Worker 
554*58e6ee5fSAndroid Build Coastguard Worker 	if (memcmp(buf, "header_page", 12) != 0)
555*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
556*58e6ee5fSAndroid Build Coastguard Worker 
557*58e6ee5fSAndroid Build Coastguard Worker 	if (read8(handle, &size) < 0)
558*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
559*58e6ee5fSAndroid Build Coastguard Worker 
560*58e6ee5fSAndroid Build Coastguard Worker 	header = malloc(size);
561*58e6ee5fSAndroid Build Coastguard Worker 	if (!header)
562*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
563*58e6ee5fSAndroid Build Coastguard Worker 
564*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, header, size))
565*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
566*58e6ee5fSAndroid Build Coastguard Worker 
567*58e6ee5fSAndroid Build Coastguard Worker 	tep_parse_header_page(pevent, header, size, handle->long_size);
568*58e6ee5fSAndroid Build Coastguard Worker 	free(header);
569*58e6ee5fSAndroid Build Coastguard Worker 
570*58e6ee5fSAndroid Build Coastguard Worker 	/*
571*58e6ee5fSAndroid Build Coastguard Worker 	 * The size field in the page is of type long,
572*58e6ee5fSAndroid Build Coastguard Worker 	 * use that instead, since it represents the kernel.
573*58e6ee5fSAndroid Build Coastguard Worker 	 */
574*58e6ee5fSAndroid Build Coastguard Worker 	handle->long_size = tep_get_header_page_size(pevent);
575*58e6ee5fSAndroid Build Coastguard Worker 
576*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, buf, 13))
577*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
578*58e6ee5fSAndroid Build Coastguard Worker 
579*58e6ee5fSAndroid Build Coastguard Worker 	if (memcmp(buf, "header_event", 13) != 0)
580*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
581*58e6ee5fSAndroid Build Coastguard Worker 
582*58e6ee5fSAndroid Build Coastguard Worker 	if (read8(handle, &size) < 0)
583*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
584*58e6ee5fSAndroid Build Coastguard Worker 
585*58e6ee5fSAndroid Build Coastguard Worker 	header = malloc(size);
586*58e6ee5fSAndroid Build Coastguard Worker 	if (!header)
587*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
588*58e6ee5fSAndroid Build Coastguard Worker 
589*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, header, size))
590*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
591*58e6ee5fSAndroid Build Coastguard Worker 
592*58e6ee5fSAndroid Build Coastguard Worker 	free(header);
593*58e6ee5fSAndroid Build Coastguard Worker 
594*58e6ee5fSAndroid Build Coastguard Worker 	handle->file_state = TRACECMD_FILE_HEADERS;
595*58e6ee5fSAndroid Build Coastguard Worker 
596*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
597*58e6ee5fSAndroid Build Coastguard Worker 
598*58e6ee5fSAndroid Build Coastguard Worker  failed_read:
599*58e6ee5fSAndroid Build Coastguard Worker 	free(header);
600*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
601*58e6ee5fSAndroid Build Coastguard Worker }
602*58e6ee5fSAndroid Build Coastguard Worker 
regex_event_buf(const char * file,int size,regex_t * epreg)603*58e6ee5fSAndroid Build Coastguard Worker static int regex_event_buf(const char *file, int size, regex_t *epreg)
604*58e6ee5fSAndroid Build Coastguard Worker {
605*58e6ee5fSAndroid Build Coastguard Worker 	char *buf;
606*58e6ee5fSAndroid Build Coastguard Worker 	char *line;
607*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
608*58e6ee5fSAndroid Build Coastguard Worker 
609*58e6ee5fSAndroid Build Coastguard Worker 	buf = malloc(size + 1);
610*58e6ee5fSAndroid Build Coastguard Worker 	if (!buf) {
611*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_warning("Insufficient memory");
612*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
613*58e6ee5fSAndroid Build Coastguard Worker 	}
614*58e6ee5fSAndroid Build Coastguard Worker 
615*58e6ee5fSAndroid Build Coastguard Worker 	strncpy(buf, file, size);
616*58e6ee5fSAndroid Build Coastguard Worker 	buf[size] = 0;
617*58e6ee5fSAndroid Build Coastguard Worker 
618*58e6ee5fSAndroid Build Coastguard Worker 	/* get the name from the first line */
619*58e6ee5fSAndroid Build Coastguard Worker 	line = strtok(buf, "\n");
620*58e6ee5fSAndroid Build Coastguard Worker 	if (!line) {
621*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_warning("No newline found in '%s'", buf);
622*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
623*58e6ee5fSAndroid Build Coastguard Worker 	}
624*58e6ee5fSAndroid Build Coastguard Worker 	/* skip name if it is there */
625*58e6ee5fSAndroid Build Coastguard Worker 	if (strncmp(line, "name: ", 6) == 0)
626*58e6ee5fSAndroid Build Coastguard Worker 		line += 6;
627*58e6ee5fSAndroid Build Coastguard Worker 
628*58e6ee5fSAndroid Build Coastguard Worker 	ret = regexec(epreg, line, 0, NULL, 0) == 0;
629*58e6ee5fSAndroid Build Coastguard Worker 
630*58e6ee5fSAndroid Build Coastguard Worker 	free(buf);
631*58e6ee5fSAndroid Build Coastguard Worker 
632*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
633*58e6ee5fSAndroid Build Coastguard Worker }
634*58e6ee5fSAndroid Build Coastguard Worker 
read_ftrace_file(struct tracecmd_input * handle,unsigned long long size,int print,regex_t * epreg)635*58e6ee5fSAndroid Build Coastguard Worker static int read_ftrace_file(struct tracecmd_input *handle,
636*58e6ee5fSAndroid Build Coastguard Worker 			    unsigned long long size,
637*58e6ee5fSAndroid Build Coastguard Worker 			    int print, regex_t *epreg)
638*58e6ee5fSAndroid Build Coastguard Worker {
639*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = handle->pevent;
640*58e6ee5fSAndroid Build Coastguard Worker 	char *buf;
641*58e6ee5fSAndroid Build Coastguard Worker 
642*58e6ee5fSAndroid Build Coastguard Worker 	buf = malloc(size);
643*58e6ee5fSAndroid Build Coastguard Worker 	if (!buf)
644*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
645*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, buf, size)) {
646*58e6ee5fSAndroid Build Coastguard Worker 		free(buf);
647*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
648*58e6ee5fSAndroid Build Coastguard Worker 	}
649*58e6ee5fSAndroid Build Coastguard Worker 
650*58e6ee5fSAndroid Build Coastguard Worker 	if (epreg) {
651*58e6ee5fSAndroid Build Coastguard Worker 		if (print || regex_event_buf(buf, size, epreg))
652*58e6ee5fSAndroid Build Coastguard Worker 			printf("%.*s\n", (int)size, buf);
653*58e6ee5fSAndroid Build Coastguard Worker 	} else {
654*58e6ee5fSAndroid Build Coastguard Worker 		if (tep_parse_event(pevent, buf, size, "ftrace"))
655*58e6ee5fSAndroid Build Coastguard Worker 			handle->parsing_failures++;
656*58e6ee5fSAndroid Build Coastguard Worker 	}
657*58e6ee5fSAndroid Build Coastguard Worker 	free(buf);
658*58e6ee5fSAndroid Build Coastguard Worker 
659*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
660*58e6ee5fSAndroid Build Coastguard Worker }
661*58e6ee5fSAndroid Build Coastguard Worker 
read_event_file(struct tracecmd_input * handle,char * system,unsigned long long size,int print,int * sys_printed,regex_t * epreg)662*58e6ee5fSAndroid Build Coastguard Worker static int read_event_file(struct tracecmd_input *handle,
663*58e6ee5fSAndroid Build Coastguard Worker 			   char *system, unsigned long long size,
664*58e6ee5fSAndroid Build Coastguard Worker 			   int print, int *sys_printed,
665*58e6ee5fSAndroid Build Coastguard Worker 			   regex_t *epreg)
666*58e6ee5fSAndroid Build Coastguard Worker {
667*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = handle->pevent;
668*58e6ee5fSAndroid Build Coastguard Worker 	char *buf;
669*58e6ee5fSAndroid Build Coastguard Worker 
670*58e6ee5fSAndroid Build Coastguard Worker 	buf = malloc(size);
671*58e6ee5fSAndroid Build Coastguard Worker 	if (!buf)
672*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
673*58e6ee5fSAndroid Build Coastguard Worker 
674*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, buf, size)) {
675*58e6ee5fSAndroid Build Coastguard Worker 		free(buf);
676*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
677*58e6ee5fSAndroid Build Coastguard Worker 	}
678*58e6ee5fSAndroid Build Coastguard Worker 
679*58e6ee5fSAndroid Build Coastguard Worker 	if (epreg) {
680*58e6ee5fSAndroid Build Coastguard Worker 		if (print || regex_event_buf(buf, size, epreg)) {
681*58e6ee5fSAndroid Build Coastguard Worker 			if (!*sys_printed) {
682*58e6ee5fSAndroid Build Coastguard Worker 				printf("\nsystem: %s\n", system);
683*58e6ee5fSAndroid Build Coastguard Worker 				*sys_printed = 1;
684*58e6ee5fSAndroid Build Coastguard Worker 			}
685*58e6ee5fSAndroid Build Coastguard Worker 			printf("%.*s\n", (int)size, buf);
686*58e6ee5fSAndroid Build Coastguard Worker 		}
687*58e6ee5fSAndroid Build Coastguard Worker 	} else {
688*58e6ee5fSAndroid Build Coastguard Worker 		if (tep_parse_event(pevent, buf, size, system))
689*58e6ee5fSAndroid Build Coastguard Worker 			handle->parsing_failures++;
690*58e6ee5fSAndroid Build Coastguard Worker 	}
691*58e6ee5fSAndroid Build Coastguard Worker 	free(buf);
692*58e6ee5fSAndroid Build Coastguard Worker 
693*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
694*58e6ee5fSAndroid Build Coastguard Worker }
695*58e6ee5fSAndroid Build Coastguard Worker 
make_preg_files(const char * regex,regex_t * system,regex_t * event,int * unique)696*58e6ee5fSAndroid Build Coastguard Worker static int make_preg_files(const char *regex, regex_t *system,
697*58e6ee5fSAndroid Build Coastguard Worker 			   regex_t *event, int *unique)
698*58e6ee5fSAndroid Build Coastguard Worker {
699*58e6ee5fSAndroid Build Coastguard Worker 	char *buf;
700*58e6ee5fSAndroid Build Coastguard Worker 	char *sstr;
701*58e6ee5fSAndroid Build Coastguard Worker 	char *estr;
702*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
703*58e6ee5fSAndroid Build Coastguard Worker 
704*58e6ee5fSAndroid Build Coastguard Worker 	/* unique is set if a colon is found */
705*58e6ee5fSAndroid Build Coastguard Worker 	*unique = 0;
706*58e6ee5fSAndroid Build Coastguard Worker 
707*58e6ee5fSAndroid Build Coastguard Worker 	/* split "system:event" into "system" and "event" */
708*58e6ee5fSAndroid Build Coastguard Worker 
709*58e6ee5fSAndroid Build Coastguard Worker 	buf = strdup(regex);
710*58e6ee5fSAndroid Build Coastguard Worker 	if (!buf)
711*58e6ee5fSAndroid Build Coastguard Worker 		return -ENOMEM;
712*58e6ee5fSAndroid Build Coastguard Worker 
713*58e6ee5fSAndroid Build Coastguard Worker 	sstr = strtok(buf, ":");
714*58e6ee5fSAndroid Build Coastguard Worker 	estr = strtok(NULL, ":");
715*58e6ee5fSAndroid Build Coastguard Worker 
716*58e6ee5fSAndroid Build Coastguard Worker 	/* If no colon is found, set event == system */
717*58e6ee5fSAndroid Build Coastguard Worker 	if (!estr)
718*58e6ee5fSAndroid Build Coastguard Worker 		estr = sstr;
719*58e6ee5fSAndroid Build Coastguard Worker 	else
720*58e6ee5fSAndroid Build Coastguard Worker 		*unique = 1;
721*58e6ee5fSAndroid Build Coastguard Worker 
722*58e6ee5fSAndroid Build Coastguard Worker 	ret = regcomp(system, sstr, REG_ICASE|REG_NOSUB);
723*58e6ee5fSAndroid Build Coastguard Worker 	if (ret) {
724*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_warning("Bad regular expression '%s'", sstr);
725*58e6ee5fSAndroid Build Coastguard Worker 		goto out;
726*58e6ee5fSAndroid Build Coastguard Worker 	}
727*58e6ee5fSAndroid Build Coastguard Worker 
728*58e6ee5fSAndroid Build Coastguard Worker 	ret = regcomp(event, estr, REG_ICASE|REG_NOSUB);
729*58e6ee5fSAndroid Build Coastguard Worker 	if (ret) {
730*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_warning("Bad regular expression '%s'", estr);
731*58e6ee5fSAndroid Build Coastguard Worker 		goto out;
732*58e6ee5fSAndroid Build Coastguard Worker 	}
733*58e6ee5fSAndroid Build Coastguard Worker 
734*58e6ee5fSAndroid Build Coastguard Worker  out:
735*58e6ee5fSAndroid Build Coastguard Worker 	free(buf);
736*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
737*58e6ee5fSAndroid Build Coastguard Worker }
738*58e6ee5fSAndroid Build Coastguard Worker 
read_ftrace_files(struct tracecmd_input * handle,const char * regex)739*58e6ee5fSAndroid Build Coastguard Worker static int read_ftrace_files(struct tracecmd_input *handle, const char *regex)
740*58e6ee5fSAndroid Build Coastguard Worker {
741*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
742*58e6ee5fSAndroid Build Coastguard Worker 	regex_t spreg;
743*58e6ee5fSAndroid Build Coastguard Worker 	regex_t epreg;
744*58e6ee5fSAndroid Build Coastguard Worker 	regex_t *sreg = NULL;
745*58e6ee5fSAndroid Build Coastguard Worker 	regex_t *ereg = NULL;
746*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int count, i;
747*58e6ee5fSAndroid Build Coastguard Worker 	int print_all = 0;
748*58e6ee5fSAndroid Build Coastguard Worker 	int unique;
749*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
750*58e6ee5fSAndroid Build Coastguard Worker 
751*58e6ee5fSAndroid Build Coastguard Worker 	if (CHECK_READ_STATE(handle, TRACECMD_FILE_FTRACE_EVENTS))
752*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
753*58e6ee5fSAndroid Build Coastguard Worker 
754*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle))
755*58e6ee5fSAndroid Build Coastguard Worker 		section_add_or_update(handle, TRACECMD_OPTION_FTRACE_EVENTS, 0, 0,
756*58e6ee5fSAndroid Build Coastguard Worker 				      lseek64(handle->fd, 0, SEEK_CUR));
757*58e6ee5fSAndroid Build Coastguard Worker 
758*58e6ee5fSAndroid Build Coastguard Worker 	if (regex) {
759*58e6ee5fSAndroid Build Coastguard Worker 		sreg = &spreg;
760*58e6ee5fSAndroid Build Coastguard Worker 		ereg = &epreg;
761*58e6ee5fSAndroid Build Coastguard Worker 		ret = make_preg_files(regex, sreg, ereg, &unique);
762*58e6ee5fSAndroid Build Coastguard Worker 		if (ret)
763*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
764*58e6ee5fSAndroid Build Coastguard Worker 
765*58e6ee5fSAndroid Build Coastguard Worker 		if (regexec(sreg, "ftrace", 0, NULL, 0) == 0) {
766*58e6ee5fSAndroid Build Coastguard Worker 			/*
767*58e6ee5fSAndroid Build Coastguard Worker 			 * If the system matches a regex that did
768*58e6ee5fSAndroid Build Coastguard Worker 			 * not contain a colon, then print all events.
769*58e6ee5fSAndroid Build Coastguard Worker 			 */
770*58e6ee5fSAndroid Build Coastguard Worker 			if (!unique)
771*58e6ee5fSAndroid Build Coastguard Worker 				print_all = 1;
772*58e6ee5fSAndroid Build Coastguard Worker 		} else if (unique) {
773*58e6ee5fSAndroid Build Coastguard Worker 			/*
774*58e6ee5fSAndroid Build Coastguard Worker 			 * The user specified a unique event that did
775*58e6ee5fSAndroid Build Coastguard Worker 			 * not match the ftrace system. Don't print any
776*58e6ee5fSAndroid Build Coastguard Worker 			 * events here.
777*58e6ee5fSAndroid Build Coastguard Worker 			 */
778*58e6ee5fSAndroid Build Coastguard Worker 			regfree(sreg);
779*58e6ee5fSAndroid Build Coastguard Worker 			regfree(ereg);
780*58e6ee5fSAndroid Build Coastguard Worker 			sreg = NULL;
781*58e6ee5fSAndroid Build Coastguard Worker 			ereg = NULL;
782*58e6ee5fSAndroid Build Coastguard Worker 		}
783*58e6ee5fSAndroid Build Coastguard Worker 	}
784*58e6ee5fSAndroid Build Coastguard Worker 
785*58e6ee5fSAndroid Build Coastguard Worker 	ret = read4(handle, &count);
786*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
787*58e6ee5fSAndroid Build Coastguard Worker 		goto out;
788*58e6ee5fSAndroid Build Coastguard Worker 
789*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < count; i++) {
790*58e6ee5fSAndroid Build Coastguard Worker 		ret = read8(handle, &size);
791*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
792*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
793*58e6ee5fSAndroid Build Coastguard Worker 		ret = read_ftrace_file(handle, size, print_all, ereg);
794*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
795*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
796*58e6ee5fSAndroid Build Coastguard Worker 	}
797*58e6ee5fSAndroid Build Coastguard Worker 
798*58e6ee5fSAndroid Build Coastguard Worker 	handle->file_state = TRACECMD_FILE_FTRACE_EVENTS;
799*58e6ee5fSAndroid Build Coastguard Worker 	ret = 0;
800*58e6ee5fSAndroid Build Coastguard Worker out:
801*58e6ee5fSAndroid Build Coastguard Worker 	if (sreg) {
802*58e6ee5fSAndroid Build Coastguard Worker 		regfree(sreg);
803*58e6ee5fSAndroid Build Coastguard Worker 		regfree(ereg);
804*58e6ee5fSAndroid Build Coastguard Worker 	}
805*58e6ee5fSAndroid Build Coastguard Worker 
806*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
807*58e6ee5fSAndroid Build Coastguard Worker }
808*58e6ee5fSAndroid Build Coastguard Worker 
read_event_files(struct tracecmd_input * handle,const char * regex)809*58e6ee5fSAndroid Build Coastguard Worker static int read_event_files(struct tracecmd_input *handle, const char *regex)
810*58e6ee5fSAndroid Build Coastguard Worker {
811*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
812*58e6ee5fSAndroid Build Coastguard Worker 	char *system = NULL;
813*58e6ee5fSAndroid Build Coastguard Worker 	regex_t spreg;
814*58e6ee5fSAndroid Build Coastguard Worker 	regex_t epreg;
815*58e6ee5fSAndroid Build Coastguard Worker 	regex_t *sreg = NULL;
816*58e6ee5fSAndroid Build Coastguard Worker 	regex_t *ereg = NULL;
817*58e6ee5fSAndroid Build Coastguard Worker 	regex_t *reg;
818*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int systems;
819*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int count;
820*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int i, x;
821*58e6ee5fSAndroid Build Coastguard Worker 	int print_all;
822*58e6ee5fSAndroid Build Coastguard Worker 	int sys_printed;
823*58e6ee5fSAndroid Build Coastguard Worker 	int unique;
824*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
825*58e6ee5fSAndroid Build Coastguard Worker 
826*58e6ee5fSAndroid Build Coastguard Worker 	if (CHECK_READ_STATE(handle, TRACECMD_FILE_ALL_EVENTS))
827*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
828*58e6ee5fSAndroid Build Coastguard Worker 
829*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle))
830*58e6ee5fSAndroid Build Coastguard Worker 		section_add_or_update(handle, TRACECMD_OPTION_EVENT_FORMATS, 0, 0,
831*58e6ee5fSAndroid Build Coastguard Worker 				      lseek64(handle->fd, 0, SEEK_CUR));
832*58e6ee5fSAndroid Build Coastguard Worker 
833*58e6ee5fSAndroid Build Coastguard Worker 	if (regex) {
834*58e6ee5fSAndroid Build Coastguard Worker 		sreg = &spreg;
835*58e6ee5fSAndroid Build Coastguard Worker 		ereg = &epreg;
836*58e6ee5fSAndroid Build Coastguard Worker 		ret = make_preg_files(regex, sreg, ereg, &unique);
837*58e6ee5fSAndroid Build Coastguard Worker 		if (ret)
838*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
839*58e6ee5fSAndroid Build Coastguard Worker 	}
840*58e6ee5fSAndroid Build Coastguard Worker 
841*58e6ee5fSAndroid Build Coastguard Worker 	ret = read4(handle, &systems);
842*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
843*58e6ee5fSAndroid Build Coastguard Worker 		goto out;
844*58e6ee5fSAndroid Build Coastguard Worker 
845*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < systems; i++) {
846*58e6ee5fSAndroid Build Coastguard Worker 		system = read_string(handle);
847*58e6ee5fSAndroid Build Coastguard Worker 		if (!system) {
848*58e6ee5fSAndroid Build Coastguard Worker 			ret = -1;
849*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
850*58e6ee5fSAndroid Build Coastguard Worker 		}
851*58e6ee5fSAndroid Build Coastguard Worker 
852*58e6ee5fSAndroid Build Coastguard Worker 		sys_printed = 0;
853*58e6ee5fSAndroid Build Coastguard Worker 		print_all = 0;
854*58e6ee5fSAndroid Build Coastguard Worker 		reg = ereg;
855*58e6ee5fSAndroid Build Coastguard Worker 
856*58e6ee5fSAndroid Build Coastguard Worker 		if (sreg) {
857*58e6ee5fSAndroid Build Coastguard Worker 			if (regexec(sreg, system, 0, NULL, 0) == 0) {
858*58e6ee5fSAndroid Build Coastguard Worker 				/*
859*58e6ee5fSAndroid Build Coastguard Worker 				 * If the user passed in a regex that
860*58e6ee5fSAndroid Build Coastguard Worker 				 * did not contain a colon, then we can
861*58e6ee5fSAndroid Build Coastguard Worker 				 * print all the events of this system.
862*58e6ee5fSAndroid Build Coastguard Worker 				 */
863*58e6ee5fSAndroid Build Coastguard Worker 				if (!unique)
864*58e6ee5fSAndroid Build Coastguard Worker 					print_all = 1;
865*58e6ee5fSAndroid Build Coastguard Worker 			} else if (unique) {
866*58e6ee5fSAndroid Build Coastguard Worker 				/*
867*58e6ee5fSAndroid Build Coastguard Worker 				 * The user passed in a unique event that
868*58e6ee5fSAndroid Build Coastguard Worker 				 * specified a specific system and event.
869*58e6ee5fSAndroid Build Coastguard Worker 				 * Since this system doesn't match this
870*58e6ee5fSAndroid Build Coastguard Worker 				 * event, then we don't print any events
871*58e6ee5fSAndroid Build Coastguard Worker 				 * for this system.
872*58e6ee5fSAndroid Build Coastguard Worker 				 */
873*58e6ee5fSAndroid Build Coastguard Worker 				reg = NULL;
874*58e6ee5fSAndroid Build Coastguard Worker 			}
875*58e6ee5fSAndroid Build Coastguard Worker 		}
876*58e6ee5fSAndroid Build Coastguard Worker 
877*58e6ee5fSAndroid Build Coastguard Worker 		ret = read4(handle, &count);
878*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
879*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
880*58e6ee5fSAndroid Build Coastguard Worker 
881*58e6ee5fSAndroid Build Coastguard Worker 		for (x=0; x < count; x++) {
882*58e6ee5fSAndroid Build Coastguard Worker 			ret = read8(handle, &size);
883*58e6ee5fSAndroid Build Coastguard Worker 			if (ret < 0)
884*58e6ee5fSAndroid Build Coastguard Worker 				goto out;
885*58e6ee5fSAndroid Build Coastguard Worker 
886*58e6ee5fSAndroid Build Coastguard Worker 			ret = read_event_file(handle, system, size,
887*58e6ee5fSAndroid Build Coastguard Worker 					      print_all, &sys_printed,
888*58e6ee5fSAndroid Build Coastguard Worker 					      reg);
889*58e6ee5fSAndroid Build Coastguard Worker 			if (ret < 0)
890*58e6ee5fSAndroid Build Coastguard Worker 				goto out;
891*58e6ee5fSAndroid Build Coastguard Worker 		}
892*58e6ee5fSAndroid Build Coastguard Worker 		free(system);
893*58e6ee5fSAndroid Build Coastguard Worker 	}
894*58e6ee5fSAndroid Build Coastguard Worker 	system = NULL;
895*58e6ee5fSAndroid Build Coastguard Worker 
896*58e6ee5fSAndroid Build Coastguard Worker 	handle->file_state = TRACECMD_FILE_ALL_EVENTS;
897*58e6ee5fSAndroid Build Coastguard Worker 	ret = 0;
898*58e6ee5fSAndroid Build Coastguard Worker  out:
899*58e6ee5fSAndroid Build Coastguard Worker 	if (sreg) {
900*58e6ee5fSAndroid Build Coastguard Worker 		regfree(sreg);
901*58e6ee5fSAndroid Build Coastguard Worker 		regfree(ereg);
902*58e6ee5fSAndroid Build Coastguard Worker 	}
903*58e6ee5fSAndroid Build Coastguard Worker 
904*58e6ee5fSAndroid Build Coastguard Worker 	free(system);
905*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
906*58e6ee5fSAndroid Build Coastguard Worker }
907*58e6ee5fSAndroid Build Coastguard Worker 
read_proc_kallsyms(struct tracecmd_input * handle)908*58e6ee5fSAndroid Build Coastguard Worker static int read_proc_kallsyms(struct tracecmd_input *handle)
909*58e6ee5fSAndroid Build Coastguard Worker {
910*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *tep = handle->pevent;
911*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int size;
912*58e6ee5fSAndroid Build Coastguard Worker 	char *buf;
913*58e6ee5fSAndroid Build Coastguard Worker 
914*58e6ee5fSAndroid Build Coastguard Worker 	if (CHECK_READ_STATE(handle, TRACECMD_FILE_KALLSYMS))
915*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
916*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle))
917*58e6ee5fSAndroid Build Coastguard Worker 		section_add_or_update(handle, TRACECMD_OPTION_KALLSYMS, 0, 0,
918*58e6ee5fSAndroid Build Coastguard Worker 				      lseek64(handle->fd, 0, SEEK_CUR));
919*58e6ee5fSAndroid Build Coastguard Worker 
920*58e6ee5fSAndroid Build Coastguard Worker 	if (read4(handle, &size) < 0)
921*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
922*58e6ee5fSAndroid Build Coastguard Worker 	if (!size) {
923*58e6ee5fSAndroid Build Coastguard Worker 		handle->file_state = TRACECMD_FILE_KALLSYMS;
924*58e6ee5fSAndroid Build Coastguard Worker 		return 0; /* OK? */
925*58e6ee5fSAndroid Build Coastguard Worker 	}
926*58e6ee5fSAndroid Build Coastguard Worker 
927*58e6ee5fSAndroid Build Coastguard Worker 	buf = malloc(size+1);
928*58e6ee5fSAndroid Build Coastguard Worker 	if (!buf)
929*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
930*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, buf, size)){
931*58e6ee5fSAndroid Build Coastguard Worker 		free(buf);
932*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
933*58e6ee5fSAndroid Build Coastguard Worker 	}
934*58e6ee5fSAndroid Build Coastguard Worker 	buf[size] = 0;
935*58e6ee5fSAndroid Build Coastguard Worker 
936*58e6ee5fSAndroid Build Coastguard Worker 	tep_parse_kallsyms(tep, buf);
937*58e6ee5fSAndroid Build Coastguard Worker 
938*58e6ee5fSAndroid Build Coastguard Worker 	free(buf);
939*58e6ee5fSAndroid Build Coastguard Worker 
940*58e6ee5fSAndroid Build Coastguard Worker 	handle->file_state = TRACECMD_FILE_KALLSYMS;
941*58e6ee5fSAndroid Build Coastguard Worker 
942*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
943*58e6ee5fSAndroid Build Coastguard Worker }
944*58e6ee5fSAndroid Build Coastguard Worker 
read_ftrace_printk(struct tracecmd_input * handle)945*58e6ee5fSAndroid Build Coastguard Worker static int read_ftrace_printk(struct tracecmd_input *handle)
946*58e6ee5fSAndroid Build Coastguard Worker {
947*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int size;
948*58e6ee5fSAndroid Build Coastguard Worker 	char *buf;
949*58e6ee5fSAndroid Build Coastguard Worker 
950*58e6ee5fSAndroid Build Coastguard Worker 	if (CHECK_READ_STATE(handle, TRACECMD_FILE_PRINTK))
951*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
952*58e6ee5fSAndroid Build Coastguard Worker 
953*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle))
954*58e6ee5fSAndroid Build Coastguard Worker 		section_add_or_update(handle, TRACECMD_OPTION_PRINTK, 0, 0,
955*58e6ee5fSAndroid Build Coastguard Worker 				      lseek64(handle->fd, 0, SEEK_CUR));
956*58e6ee5fSAndroid Build Coastguard Worker 
957*58e6ee5fSAndroid Build Coastguard Worker 	if (read4(handle, &size) < 0)
958*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
959*58e6ee5fSAndroid Build Coastguard Worker 	if (!size) {
960*58e6ee5fSAndroid Build Coastguard Worker 		handle->file_state = TRACECMD_FILE_PRINTK;
961*58e6ee5fSAndroid Build Coastguard Worker 		return 0; /* OK? */
962*58e6ee5fSAndroid Build Coastguard Worker 	}
963*58e6ee5fSAndroid Build Coastguard Worker 
964*58e6ee5fSAndroid Build Coastguard Worker 	buf = malloc(size + 1);
965*58e6ee5fSAndroid Build Coastguard Worker 	if (!buf)
966*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
967*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, buf, size)) {
968*58e6ee5fSAndroid Build Coastguard Worker 		free(buf);
969*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
970*58e6ee5fSAndroid Build Coastguard Worker 	}
971*58e6ee5fSAndroid Build Coastguard Worker 
972*58e6ee5fSAndroid Build Coastguard Worker 	buf[size] = 0;
973*58e6ee5fSAndroid Build Coastguard Worker 
974*58e6ee5fSAndroid Build Coastguard Worker 	tep_parse_printk_formats(handle->pevent, buf);
975*58e6ee5fSAndroid Build Coastguard Worker 
976*58e6ee5fSAndroid Build Coastguard Worker 	free(buf);
977*58e6ee5fSAndroid Build Coastguard Worker 
978*58e6ee5fSAndroid Build Coastguard Worker 	handle->file_state = TRACECMD_FILE_PRINTK;
979*58e6ee5fSAndroid Build Coastguard Worker 
980*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
981*58e6ee5fSAndroid Build Coastguard Worker }
982*58e6ee5fSAndroid Build Coastguard Worker 
983*58e6ee5fSAndroid Build Coastguard Worker static int read_and_parse_cmdlines(struct tracecmd_input *handle);
984*58e6ee5fSAndroid Build Coastguard Worker 
985*58e6ee5fSAndroid Build Coastguard Worker /**
986*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_parsing_failures - get the count of parsing failures
987*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
988*58e6ee5fSAndroid Build Coastguard Worker  *
989*58e6ee5fSAndroid Build Coastguard Worker  * This returns the count of failures while parsing the event files
990*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_parsing_failures(struct tracecmd_input * handle)991*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_get_parsing_failures(struct tracecmd_input *handle)
992*58e6ee5fSAndroid Build Coastguard Worker {
993*58e6ee5fSAndroid Build Coastguard Worker 	if (handle)
994*58e6ee5fSAndroid Build Coastguard Worker 		return handle->parsing_failures;
995*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
996*58e6ee5fSAndroid Build Coastguard Worker }
997*58e6ee5fSAndroid Build Coastguard Worker 
read_cpus(struct tracecmd_input * handle)998*58e6ee5fSAndroid Build Coastguard Worker static int read_cpus(struct tracecmd_input *handle)
999*58e6ee5fSAndroid Build Coastguard Worker {
1000*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int cpus;
1001*58e6ee5fSAndroid Build Coastguard Worker 
1002*58e6ee5fSAndroid Build Coastguard Worker 	if (CHECK_READ_STATE(handle, TRACECMD_FILE_CPU_COUNT))
1003*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1004*58e6ee5fSAndroid Build Coastguard Worker 
1005*58e6ee5fSAndroid Build Coastguard Worker 	if (read4(handle, &cpus) < 0)
1006*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1007*58e6ee5fSAndroid Build Coastguard Worker 
1008*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpus = cpus;
1009*58e6ee5fSAndroid Build Coastguard Worker 	handle->max_cpu = cpus;
1010*58e6ee5fSAndroid Build Coastguard Worker 	tep_set_cpus(handle->pevent, handle->cpus);
1011*58e6ee5fSAndroid Build Coastguard Worker 	handle->file_state = TRACECMD_FILE_CPU_COUNT;
1012*58e6ee5fSAndroid Build Coastguard Worker 
1013*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1014*58e6ee5fSAndroid Build Coastguard Worker }
1015*58e6ee5fSAndroid Build Coastguard Worker 
read_headers_v6(struct tracecmd_input * handle,enum tracecmd_file_states state,const char * regex)1016*58e6ee5fSAndroid Build Coastguard Worker static int read_headers_v6(struct tracecmd_input *handle, enum tracecmd_file_states state,
1017*58e6ee5fSAndroid Build Coastguard Worker 			   const char *regex)
1018*58e6ee5fSAndroid Build Coastguard Worker {
1019*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
1020*58e6ee5fSAndroid Build Coastguard Worker 
1021*58e6ee5fSAndroid Build Coastguard Worker 	/* Set to read all if state is zero */
1022*58e6ee5fSAndroid Build Coastguard Worker 	if (!state)
1023*58e6ee5fSAndroid Build Coastguard Worker 		state = TRACECMD_FILE_OPTIONS;
1024*58e6ee5fSAndroid Build Coastguard Worker 
1025*58e6ee5fSAndroid Build Coastguard Worker 	if (state <= handle->file_state)
1026*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1027*58e6ee5fSAndroid Build Coastguard Worker 
1028*58e6ee5fSAndroid Build Coastguard Worker 	handle->parsing_failures = 0;
1029*58e6ee5fSAndroid Build Coastguard Worker 
1030*58e6ee5fSAndroid Build Coastguard Worker 	ret = read_header_files(handle);
1031*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
1032*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1033*58e6ee5fSAndroid Build Coastguard Worker 
1034*58e6ee5fSAndroid Build Coastguard Worker 	if (state <= handle->file_state)
1035*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1036*58e6ee5fSAndroid Build Coastguard Worker 
1037*58e6ee5fSAndroid Build Coastguard Worker 	ret = read_ftrace_files(handle, NULL);
1038*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
1039*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1040*58e6ee5fSAndroid Build Coastguard Worker 
1041*58e6ee5fSAndroid Build Coastguard Worker 	if (state <= handle->file_state)
1042*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1043*58e6ee5fSAndroid Build Coastguard Worker 
1044*58e6ee5fSAndroid Build Coastguard Worker 	ret = read_event_files(handle, regex);
1045*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
1046*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1047*58e6ee5fSAndroid Build Coastguard Worker 
1048*58e6ee5fSAndroid Build Coastguard Worker 	if (state <= handle->file_state)
1049*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1050*58e6ee5fSAndroid Build Coastguard Worker 
1051*58e6ee5fSAndroid Build Coastguard Worker 	ret = read_proc_kallsyms(handle);
1052*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
1053*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1054*58e6ee5fSAndroid Build Coastguard Worker 
1055*58e6ee5fSAndroid Build Coastguard Worker 	if (state <= handle->file_state)
1056*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1057*58e6ee5fSAndroid Build Coastguard Worker 
1058*58e6ee5fSAndroid Build Coastguard Worker 	ret = read_ftrace_printk(handle);
1059*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
1060*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1061*58e6ee5fSAndroid Build Coastguard Worker 
1062*58e6ee5fSAndroid Build Coastguard Worker 	if (state <= handle->file_state)
1063*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1064*58e6ee5fSAndroid Build Coastguard Worker 
1065*58e6ee5fSAndroid Build Coastguard Worker 	if (read_and_parse_cmdlines(handle) < 0)
1066*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1067*58e6ee5fSAndroid Build Coastguard Worker 
1068*58e6ee5fSAndroid Build Coastguard Worker 	if (state <= handle->file_state)
1069*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1070*58e6ee5fSAndroid Build Coastguard Worker 
1071*58e6ee5fSAndroid Build Coastguard Worker 	if (read_cpus(handle) < 0)
1072*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1073*58e6ee5fSAndroid Build Coastguard Worker 
1074*58e6ee5fSAndroid Build Coastguard Worker 	if (state <= handle->file_state)
1075*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1076*58e6ee5fSAndroid Build Coastguard Worker 
1077*58e6ee5fSAndroid Build Coastguard Worker 	if (read_options_type(handle) < 0)
1078*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1079*58e6ee5fSAndroid Build Coastguard Worker 
1080*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1081*58e6ee5fSAndroid Build Coastguard Worker }
1082*58e6ee5fSAndroid Build Coastguard Worker 
1083*58e6ee5fSAndroid Build Coastguard Worker static int handle_options(struct tracecmd_input *handle);
1084*58e6ee5fSAndroid Build Coastguard Worker 
get_metadata_string(struct tracecmd_input * handle,int offset)1085*58e6ee5fSAndroid Build Coastguard Worker static const char *get_metadata_string(struct tracecmd_input *handle, int offset)
1086*58e6ee5fSAndroid Build Coastguard Worker {
1087*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle || !handle->strings || offset < 0 || handle->strings_size >= offset)
1088*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1089*58e6ee5fSAndroid Build Coastguard Worker 
1090*58e6ee5fSAndroid Build Coastguard Worker 	return handle->strings + offset;
1091*58e6ee5fSAndroid Build Coastguard Worker }
1092*58e6ee5fSAndroid Build Coastguard Worker 
read_section_header(struct tracecmd_input * handle,unsigned short * id,unsigned short * flags,unsigned long long * size,const char ** description)1093*58e6ee5fSAndroid Build Coastguard Worker static int read_section_header(struct tracecmd_input *handle, unsigned short *id,
1094*58e6ee5fSAndroid Build Coastguard Worker 			       unsigned short *flags, unsigned long long *size, const char **description)
1095*58e6ee5fSAndroid Build Coastguard Worker {
1096*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short fl;
1097*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short sec_id;
1098*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long sz;
1099*58e6ee5fSAndroid Build Coastguard Worker 	int desc;
1100*58e6ee5fSAndroid Build Coastguard Worker 
1101*58e6ee5fSAndroid Build Coastguard Worker 	if (read2(handle, &sec_id))
1102*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1103*58e6ee5fSAndroid Build Coastguard Worker 	if (read2(handle, &fl))
1104*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1105*58e6ee5fSAndroid Build Coastguard Worker 	if (read4(handle, (unsigned int *)&desc))
1106*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1107*58e6ee5fSAndroid Build Coastguard Worker 	if (read8(handle, &sz))
1108*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1109*58e6ee5fSAndroid Build Coastguard Worker 
1110*58e6ee5fSAndroid Build Coastguard Worker 	if (id)
1111*58e6ee5fSAndroid Build Coastguard Worker 		*id = sec_id;
1112*58e6ee5fSAndroid Build Coastguard Worker 	if (flags)
1113*58e6ee5fSAndroid Build Coastguard Worker 		*flags = fl;
1114*58e6ee5fSAndroid Build Coastguard Worker 	if (size)
1115*58e6ee5fSAndroid Build Coastguard Worker 		*size = sz;
1116*58e6ee5fSAndroid Build Coastguard Worker 	if (description)
1117*58e6ee5fSAndroid Build Coastguard Worker 		*description = get_metadata_string(handle, desc);
1118*58e6ee5fSAndroid Build Coastguard Worker 
1119*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1120*58e6ee5fSAndroid Build Coastguard Worker }
1121*58e6ee5fSAndroid Build Coastguard Worker 
handle_section(struct tracecmd_input * handle,struct file_section * section,const char * regex)1122*58e6ee5fSAndroid Build Coastguard Worker static int handle_section(struct tracecmd_input *handle, struct file_section *section,
1123*58e6ee5fSAndroid Build Coastguard Worker 			  const char *regex)
1124*58e6ee5fSAndroid Build Coastguard Worker {
1125*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short id, flags;
1126*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
1127*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
1128*58e6ee5fSAndroid Build Coastguard Worker 
1129*58e6ee5fSAndroid Build Coastguard Worker 	if (lseek64(handle->fd, section->section_offset, SEEK_SET) == (off_t)-1)
1130*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1131*58e6ee5fSAndroid Build Coastguard Worker 	if (read_section_header(handle, &id, &flags, &size, NULL))
1132*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1133*58e6ee5fSAndroid Build Coastguard Worker 	section->flags = flags;
1134*58e6ee5fSAndroid Build Coastguard Worker 	if (id != section->id)
1135*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1136*58e6ee5fSAndroid Build Coastguard Worker 
1137*58e6ee5fSAndroid Build Coastguard Worker 	section->data_offset = lseek64(handle->fd, 0, SEEK_CUR);
1138*58e6ee5fSAndroid Build Coastguard Worker 	if ((section->flags & TRACECMD_SEC_FL_COMPRESS) && in_uncompress_block(handle))
1139*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1140*58e6ee5fSAndroid Build Coastguard Worker 
1141*58e6ee5fSAndroid Build Coastguard Worker 	switch (section->id) {
1142*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_OPTION_HEADER_INFO:
1143*58e6ee5fSAndroid Build Coastguard Worker 		ret = read_header_files(handle);
1144*58e6ee5fSAndroid Build Coastguard Worker 		break;
1145*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_OPTION_FTRACE_EVENTS:
1146*58e6ee5fSAndroid Build Coastguard Worker 		ret = read_ftrace_files(handle, NULL);
1147*58e6ee5fSAndroid Build Coastguard Worker 		break;
1148*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_OPTION_EVENT_FORMATS:
1149*58e6ee5fSAndroid Build Coastguard Worker 		ret = read_event_files(handle, regex);
1150*58e6ee5fSAndroid Build Coastguard Worker 		break;
1151*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_OPTION_KALLSYMS:
1152*58e6ee5fSAndroid Build Coastguard Worker 		ret = read_proc_kallsyms(handle);
1153*58e6ee5fSAndroid Build Coastguard Worker 		break;
1154*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_OPTION_PRINTK:
1155*58e6ee5fSAndroid Build Coastguard Worker 		ret = read_ftrace_printk(handle);
1156*58e6ee5fSAndroid Build Coastguard Worker 		break;
1157*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_OPTION_CMDLINES:
1158*58e6ee5fSAndroid Build Coastguard Worker 		ret = read_and_parse_cmdlines(handle);
1159*58e6ee5fSAndroid Build Coastguard Worker 		break;
1160*58e6ee5fSAndroid Build Coastguard Worker 	default:
1161*58e6ee5fSAndroid Build Coastguard Worker 		ret = 0;
1162*58e6ee5fSAndroid Build Coastguard Worker 		break;
1163*58e6ee5fSAndroid Build Coastguard Worker 	}
1164*58e6ee5fSAndroid Build Coastguard Worker 
1165*58e6ee5fSAndroid Build Coastguard Worker 	if (section->flags & TRACECMD_SEC_FL_COMPRESS)
1166*58e6ee5fSAndroid Build Coastguard Worker 		in_uncompress_reset(handle);
1167*58e6ee5fSAndroid Build Coastguard Worker 
1168*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
1169*58e6ee5fSAndroid Build Coastguard Worker }
1170*58e6ee5fSAndroid Build Coastguard Worker 
read_headers(struct tracecmd_input * handle,const char * regex)1171*58e6ee5fSAndroid Build Coastguard Worker static int read_headers(struct tracecmd_input *handle, const char *regex)
1172*58e6ee5fSAndroid Build Coastguard Worker {
1173*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *section;
1174*58e6ee5fSAndroid Build Coastguard Worker 
1175*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->options_init)
1176*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1177*58e6ee5fSAndroid Build Coastguard Worker 
1178*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->options_start)
1179*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1180*58e6ee5fSAndroid Build Coastguard Worker 
1181*58e6ee5fSAndroid Build Coastguard Worker 	if (lseek64(handle->fd, handle->options_start, SEEK_SET) == (off64_t)-1) {
1182*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_warning("Filed to goto options offset %lld", handle->options_start);
1183*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1184*58e6ee5fSAndroid Build Coastguard Worker 	}
1185*58e6ee5fSAndroid Build Coastguard Worker 
1186*58e6ee5fSAndroid Build Coastguard Worker 	if (handle_options(handle))
1187*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1188*58e6ee5fSAndroid Build Coastguard Worker 
1189*58e6ee5fSAndroid Build Coastguard Worker 	section = handle->sections;
1190*58e6ee5fSAndroid Build Coastguard Worker 	while (section) {
1191*58e6ee5fSAndroid Build Coastguard Worker 		if (handle_section(handle, section, NULL))
1192*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
1193*58e6ee5fSAndroid Build Coastguard Worker 		section = section->next;
1194*58e6ee5fSAndroid Build Coastguard Worker 	}
1195*58e6ee5fSAndroid Build Coastguard Worker 
1196*58e6ee5fSAndroid Build Coastguard Worker 	handle->options_init = true;
1197*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1198*58e6ee5fSAndroid Build Coastguard Worker }
1199*58e6ee5fSAndroid Build Coastguard Worker 
1200*58e6ee5fSAndroid Build Coastguard Worker /**
1201*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_read_headers - read the header information from trace.dat
1202*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
1203*58e6ee5fSAndroid Build Coastguard Worker  * @state: The state to read up to or zero to read up to options.
1204*58e6ee5fSAndroid Build Coastguard Worker  *
1205*58e6ee5fSAndroid Build Coastguard Worker  * This reads the trace.dat file for various information. Like the
1206*58e6ee5fSAndroid Build Coastguard Worker  * format of the ring buffer, event formats, ftrace formats, kallsyms
1207*58e6ee5fSAndroid Build Coastguard Worker  * and printk. This may be called multiple times with different @state
1208*58e6ee5fSAndroid Build Coastguard Worker  * values, to read partial data at a time. It will always continue
1209*58e6ee5fSAndroid Build Coastguard Worker  * where it left off.
1210*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_read_headers(struct tracecmd_input * handle,enum tracecmd_file_states state)1211*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_read_headers(struct tracecmd_input *handle,
1212*58e6ee5fSAndroid Build Coastguard Worker 			  enum tracecmd_file_states state)
1213*58e6ee5fSAndroid Build Coastguard Worker {
1214*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle))
1215*58e6ee5fSAndroid Build Coastguard Worker 		return read_headers_v6(handle, state, NULL);
1216*58e6ee5fSAndroid Build Coastguard Worker 	return read_headers(handle, NULL);
1217*58e6ee5fSAndroid Build Coastguard Worker }
1218*58e6ee5fSAndroid Build Coastguard Worker 
calc_page_offset(struct tracecmd_input * handle,unsigned long long offset)1219*58e6ee5fSAndroid Build Coastguard Worker static unsigned long long calc_page_offset(struct tracecmd_input *handle,
1220*58e6ee5fSAndroid Build Coastguard Worker 					   unsigned long long offset)
1221*58e6ee5fSAndroid Build Coastguard Worker {
1222*58e6ee5fSAndroid Build Coastguard Worker 	return offset & ~(handle->page_size - 1);
1223*58e6ee5fSAndroid Build Coastguard Worker }
1224*58e6ee5fSAndroid Build Coastguard Worker 
read_page(struct tracecmd_input * handle,off64_t offset,int cpu,void * map)1225*58e6ee5fSAndroid Build Coastguard Worker static int read_page(struct tracecmd_input *handle, off64_t offset,
1226*58e6ee5fSAndroid Build Coastguard Worker 		     int cpu, void *map)
1227*58e6ee5fSAndroid Build Coastguard Worker {
1228*58e6ee5fSAndroid Build Coastguard Worker 	off64_t save_seek;
1229*58e6ee5fSAndroid Build Coastguard Worker 	off64_t ret;
1230*58e6ee5fSAndroid Build Coastguard Worker 
1231*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->use_pipe) {
1232*58e6ee5fSAndroid Build Coastguard Worker 		ret = read(handle->cpu_data[cpu].pipe_fd, map, handle->page_size);
1233*58e6ee5fSAndroid Build Coastguard Worker 		/* Set EAGAIN if the pipe is empty */
1234*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0) {
1235*58e6ee5fSAndroid Build Coastguard Worker 			errno = EAGAIN;
1236*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
1237*58e6ee5fSAndroid Build Coastguard Worker 
1238*58e6ee5fSAndroid Build Coastguard Worker 		} else if (ret == 0) {
1239*58e6ee5fSAndroid Build Coastguard Worker 			/* Set EINVAL when the pipe has closed */
1240*58e6ee5fSAndroid Build Coastguard Worker 			errno = EINVAL;
1241*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
1242*58e6ee5fSAndroid Build Coastguard Worker 		}
1243*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1244*58e6ee5fSAndroid Build Coastguard Worker 	}
1245*58e6ee5fSAndroid Build Coastguard Worker 
1246*58e6ee5fSAndroid Build Coastguard Worker 	/* other parts of the code may expect the pointer to not move */
1247*58e6ee5fSAndroid Build Coastguard Worker 	save_seek = lseek64(handle->fd, 0, SEEK_CUR);
1248*58e6ee5fSAndroid Build Coastguard Worker 
1249*58e6ee5fSAndroid Build Coastguard Worker 	ret = lseek64(handle->fd, offset, SEEK_SET);
1250*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
1251*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1252*58e6ee5fSAndroid Build Coastguard Worker 	ret = read(handle->fd, map, handle->page_size);
1253*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
1254*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1255*58e6ee5fSAndroid Build Coastguard Worker 
1256*58e6ee5fSAndroid Build Coastguard Worker 	/* reset the file pointer back */
1257*58e6ee5fSAndroid Build Coastguard Worker 	lseek64(handle->fd, save_seek, SEEK_SET);
1258*58e6ee5fSAndroid Build Coastguard Worker 
1259*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1260*58e6ee5fSAndroid Build Coastguard Worker }
1261*58e6ee5fSAndroid Build Coastguard Worker 
1262*58e6ee5fSAndroid Build Coastguard Worker /* page_map_size must be a power of two */
normalize_size(unsigned long long size)1263*58e6ee5fSAndroid Build Coastguard Worker static unsigned long long normalize_size(unsigned long long size)
1264*58e6ee5fSAndroid Build Coastguard Worker {
1265*58e6ee5fSAndroid Build Coastguard Worker 	/* From Hacker's Delight: or bits after first set bit to all 1s */
1266*58e6ee5fSAndroid Build Coastguard Worker 	size |= (size >> 1);
1267*58e6ee5fSAndroid Build Coastguard Worker 	size |= (size >> 2);
1268*58e6ee5fSAndroid Build Coastguard Worker 	size |= (size >> 4);
1269*58e6ee5fSAndroid Build Coastguard Worker 	size |= (size >> 8);
1270*58e6ee5fSAndroid Build Coastguard Worker 	size |= (size >> 16);
1271*58e6ee5fSAndroid Build Coastguard Worker 	size |= (size >> 32);
1272*58e6ee5fSAndroid Build Coastguard Worker 
1273*58e6ee5fSAndroid Build Coastguard Worker 	/* Clear all bits except first one for previous power of two */
1274*58e6ee5fSAndroid Build Coastguard Worker 	return size - (size >> 1);
1275*58e6ee5fSAndroid Build Coastguard Worker }
1276*58e6ee5fSAndroid Build Coastguard Worker 
free_page_map(struct page_map * page_map)1277*58e6ee5fSAndroid Build Coastguard Worker static void free_page_map(struct page_map *page_map)
1278*58e6ee5fSAndroid Build Coastguard Worker {
1279*58e6ee5fSAndroid Build Coastguard Worker 	page_map->ref_count--;
1280*58e6ee5fSAndroid Build Coastguard Worker 	if (page_map->ref_count)
1281*58e6ee5fSAndroid Build Coastguard Worker 		return;
1282*58e6ee5fSAndroid Build Coastguard Worker 
1283*58e6ee5fSAndroid Build Coastguard Worker 	munmap(page_map->map, page_map->size);
1284*58e6ee5fSAndroid Build Coastguard Worker 	list_del(&page_map->list);
1285*58e6ee5fSAndroid Build Coastguard Worker 	free(page_map);
1286*58e6ee5fSAndroid Build Coastguard Worker }
1287*58e6ee5fSAndroid Build Coastguard Worker 
1288*58e6ee5fSAndroid Build Coastguard Worker #define CHUNK_CHECK_OFFSET(C, O)	((O) >= (C)->offset && (O) < ((C)->offset + (C)->size))
1289*58e6ee5fSAndroid Build Coastguard Worker 
chunk_cmp(const void * A,const void * B)1290*58e6ee5fSAndroid Build Coastguard Worker static int chunk_cmp(const void *A, const void *B)
1291*58e6ee5fSAndroid Build Coastguard Worker {
1292*58e6ee5fSAndroid Build Coastguard Worker 	const struct tracecmd_compress_chunk *a = A;
1293*58e6ee5fSAndroid Build Coastguard Worker 	const struct tracecmd_compress_chunk *b = B;
1294*58e6ee5fSAndroid Build Coastguard Worker 
1295*58e6ee5fSAndroid Build Coastguard Worker 	if (CHUNK_CHECK_OFFSET(b, a->offset))
1296*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1297*58e6ee5fSAndroid Build Coastguard Worker 
1298*58e6ee5fSAndroid Build Coastguard Worker 	if (b->offset < a->offset)
1299*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1300*58e6ee5fSAndroid Build Coastguard Worker 
1301*58e6ee5fSAndroid Build Coastguard Worker 	return 1;
1302*58e6ee5fSAndroid Build Coastguard Worker }
1303*58e6ee5fSAndroid Build Coastguard Worker 
get_zchunk(struct cpu_data * cpu,off64_t offset)1304*58e6ee5fSAndroid Build Coastguard Worker static struct tracecmd_compress_chunk *get_zchunk(struct cpu_data *cpu, off64_t offset)
1305*58e6ee5fSAndroid Build Coastguard Worker {
1306*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_zdata *cpuz = &cpu->compress;
1307*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_compress_chunk *chunk;
1308*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_compress_chunk key;
1309*58e6ee5fSAndroid Build Coastguard Worker 
1310*58e6ee5fSAndroid Build Coastguard Worker 	if (!cpuz->chunks)
1311*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1312*58e6ee5fSAndroid Build Coastguard Worker 
1313*58e6ee5fSAndroid Build Coastguard Worker 	if (offset > (cpuz->chunks[cpuz->count - 1].offset + cpuz->chunks[cpuz->count - 1].size))
1314*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1315*58e6ee5fSAndroid Build Coastguard Worker 
1316*58e6ee5fSAndroid Build Coastguard Worker 	/* check if the requested offset is in the last requested chunk or in the next chunk */
1317*58e6ee5fSAndroid Build Coastguard Worker 	if (CHUNK_CHECK_OFFSET(cpuz->chunks + cpuz->last_chunk, offset))
1318*58e6ee5fSAndroid Build Coastguard Worker 		return cpuz->chunks + cpuz->last_chunk;
1319*58e6ee5fSAndroid Build Coastguard Worker 
1320*58e6ee5fSAndroid Build Coastguard Worker 	cpuz->last_chunk++;
1321*58e6ee5fSAndroid Build Coastguard Worker 	if (cpuz->last_chunk < cpuz->count &&
1322*58e6ee5fSAndroid Build Coastguard Worker 	    CHUNK_CHECK_OFFSET(cpuz->chunks + cpuz->last_chunk, offset))
1323*58e6ee5fSAndroid Build Coastguard Worker 		return cpuz->chunks + cpuz->last_chunk;
1324*58e6ee5fSAndroid Build Coastguard Worker 
1325*58e6ee5fSAndroid Build Coastguard Worker 	key.offset = offset;
1326*58e6ee5fSAndroid Build Coastguard Worker 	chunk = bsearch(&key, cpuz->chunks, cpuz->count, sizeof(*chunk), chunk_cmp);
1327*58e6ee5fSAndroid Build Coastguard Worker 
1328*58e6ee5fSAndroid Build Coastguard Worker 	if (!chunk) /* should never happen */
1329*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1330*58e6ee5fSAndroid Build Coastguard Worker 
1331*58e6ee5fSAndroid Build Coastguard Worker 	cpuz->last_chunk = chunk - cpuz->chunks;
1332*58e6ee5fSAndroid Build Coastguard Worker 	return chunk;
1333*58e6ee5fSAndroid Build Coastguard Worker }
1334*58e6ee5fSAndroid Build Coastguard Worker 
free_zpage(struct cpu_data * cpu_data,void * map)1335*58e6ee5fSAndroid Build Coastguard Worker static void free_zpage(struct cpu_data *cpu_data, void *map)
1336*58e6ee5fSAndroid Build Coastguard Worker {
1337*58e6ee5fSAndroid Build Coastguard Worker 	struct zchunk_cache *cache;
1338*58e6ee5fSAndroid Build Coastguard Worker 
1339*58e6ee5fSAndroid Build Coastguard Worker 	list_for_each_entry(cache, &cpu_data->compress.cache, list) {
1340*58e6ee5fSAndroid Build Coastguard Worker 		if (map <= cache->map && map > (cache->map + cache->chunk->size))
1341*58e6ee5fSAndroid Build Coastguard Worker 			goto found;
1342*58e6ee5fSAndroid Build Coastguard Worker 	}
1343*58e6ee5fSAndroid Build Coastguard Worker 	return;
1344*58e6ee5fSAndroid Build Coastguard Worker 
1345*58e6ee5fSAndroid Build Coastguard Worker found:
1346*58e6ee5fSAndroid Build Coastguard Worker 	cache->ref--;
1347*58e6ee5fSAndroid Build Coastguard Worker 	if (cache->ref)
1348*58e6ee5fSAndroid Build Coastguard Worker 		return;
1349*58e6ee5fSAndroid Build Coastguard Worker 	list_del(&cache->list);
1350*58e6ee5fSAndroid Build Coastguard Worker 	free(cache->map);
1351*58e6ee5fSAndroid Build Coastguard Worker 	free(cache);
1352*58e6ee5fSAndroid Build Coastguard Worker }
1353*58e6ee5fSAndroid Build Coastguard Worker 
read_zpage(struct tracecmd_input * handle,int cpu,off64_t offset)1354*58e6ee5fSAndroid Build Coastguard Worker static void *read_zpage(struct tracecmd_input *handle, int cpu, off64_t offset)
1355*58e6ee5fSAndroid Build Coastguard Worker {
1356*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data = &handle->cpu_data[cpu];
1357*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_compress_chunk *chunk;
1358*58e6ee5fSAndroid Build Coastguard Worker 	struct zchunk_cache *cache;
1359*58e6ee5fSAndroid Build Coastguard Worker 	void *map = NULL;
1360*58e6ee5fSAndroid Build Coastguard Worker 	int pindex;
1361*58e6ee5fSAndroid Build Coastguard Worker 	int size;
1362*58e6ee5fSAndroid Build Coastguard Worker 
1363*58e6ee5fSAndroid Build Coastguard Worker 	offset -= cpu_data->file_offset;
1364*58e6ee5fSAndroid Build Coastguard Worker 
1365*58e6ee5fSAndroid Build Coastguard Worker 	/* Look in the cache of already loaded chunks */
1366*58e6ee5fSAndroid Build Coastguard Worker 	list_for_each_entry(cache, &cpu_data->compress.cache, list) {
1367*58e6ee5fSAndroid Build Coastguard Worker 		if (CHUNK_CHECK_OFFSET(cache->chunk, offset)) {
1368*58e6ee5fSAndroid Build Coastguard Worker 			cache->ref++;
1369*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
1370*58e6ee5fSAndroid Build Coastguard Worker 		}
1371*58e6ee5fSAndroid Build Coastguard Worker 	}
1372*58e6ee5fSAndroid Build Coastguard Worker 
1373*58e6ee5fSAndroid Build Coastguard Worker 	chunk =  get_zchunk(cpu_data, offset);
1374*58e6ee5fSAndroid Build Coastguard Worker 	if (!chunk)
1375*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1376*58e6ee5fSAndroid Build Coastguard Worker 
1377*58e6ee5fSAndroid Build Coastguard Worker 	size = handle->page_size > chunk->size ? handle->page_size : chunk->size;
1378*58e6ee5fSAndroid Build Coastguard Worker 	map = malloc(size);
1379*58e6ee5fSAndroid Build Coastguard Worker 	if (!map)
1380*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1381*58e6ee5fSAndroid Build Coastguard Worker 
1382*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_uncompress_chunk(handle->compress, chunk, map) < 0)
1383*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
1384*58e6ee5fSAndroid Build Coastguard Worker 
1385*58e6ee5fSAndroid Build Coastguard Worker 	cache = calloc(1, sizeof(struct zchunk_cache));
1386*58e6ee5fSAndroid Build Coastguard Worker 	if (!cache)
1387*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
1388*58e6ee5fSAndroid Build Coastguard Worker 
1389*58e6ee5fSAndroid Build Coastguard Worker 	cache->ref = 1;
1390*58e6ee5fSAndroid Build Coastguard Worker 	cache->chunk = chunk;
1391*58e6ee5fSAndroid Build Coastguard Worker 	cache->map = map;
1392*58e6ee5fSAndroid Build Coastguard Worker 	list_add(&cache->list, &cpu_data->compress.cache);
1393*58e6ee5fSAndroid Build Coastguard Worker 
1394*58e6ee5fSAndroid Build Coastguard Worker 	/* a chunk can hold multiple pages, get the requested one */
1395*58e6ee5fSAndroid Build Coastguard Worker out:
1396*58e6ee5fSAndroid Build Coastguard Worker 	pindex = (offset - cache->chunk->offset) / handle->page_size;
1397*58e6ee5fSAndroid Build Coastguard Worker 	return cache->map + (pindex * handle->page_size);
1398*58e6ee5fSAndroid Build Coastguard Worker error:
1399*58e6ee5fSAndroid Build Coastguard Worker 	free(map);
1400*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
1401*58e6ee5fSAndroid Build Coastguard Worker }
1402*58e6ee5fSAndroid Build Coastguard Worker 
allocate_page_map(struct tracecmd_input * handle,struct page * page,int cpu,off64_t offset)1403*58e6ee5fSAndroid Build Coastguard Worker static void *allocate_page_map(struct tracecmd_input *handle,
1404*58e6ee5fSAndroid Build Coastguard Worker 			       struct page *page, int cpu, off64_t offset)
1405*58e6ee5fSAndroid Build Coastguard Worker {
1406*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data = &handle->cpu_data[cpu];
1407*58e6ee5fSAndroid Build Coastguard Worker 	struct page_map *page_map;
1408*58e6ee5fSAndroid Build Coastguard Worker 	off64_t map_size;
1409*58e6ee5fSAndroid Build Coastguard Worker 	off64_t map_offset;
1410*58e6ee5fSAndroid Build Coastguard Worker 	void *map;
1411*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
1412*58e6ee5fSAndroid Build Coastguard Worker 	int fd;
1413*58e6ee5fSAndroid Build Coastguard Worker 
1414*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->cpu_compressed && handle->read_zpage)
1415*58e6ee5fSAndroid Build Coastguard Worker 		return read_zpage(handle, cpu, offset);
1416*58e6ee5fSAndroid Build Coastguard Worker 
1417*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->read_page) {
1418*58e6ee5fSAndroid Build Coastguard Worker 		map = malloc(handle->page_size);
1419*58e6ee5fSAndroid Build Coastguard Worker 		if (!map)
1420*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
1421*58e6ee5fSAndroid Build Coastguard Worker 		ret = read_page(handle, offset, cpu, map);
1422*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0) {
1423*58e6ee5fSAndroid Build Coastguard Worker 			free(map);
1424*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
1425*58e6ee5fSAndroid Build Coastguard Worker 		}
1426*58e6ee5fSAndroid Build Coastguard Worker 		return map;
1427*58e6ee5fSAndroid Build Coastguard Worker 	}
1428*58e6ee5fSAndroid Build Coastguard Worker 
1429*58e6ee5fSAndroid Build Coastguard Worker 	map_size = handle->page_map_size;
1430*58e6ee5fSAndroid Build Coastguard Worker 	map_offset = offset & ~(map_size - 1);
1431*58e6ee5fSAndroid Build Coastguard Worker 
1432*58e6ee5fSAndroid Build Coastguard Worker 	if (map_offset < cpu_data->file_offset) {
1433*58e6ee5fSAndroid Build Coastguard Worker 		map_size -= cpu_data->file_offset - map_offset;
1434*58e6ee5fSAndroid Build Coastguard Worker 		map_offset = cpu_data->file_offset;
1435*58e6ee5fSAndroid Build Coastguard Worker 	}
1436*58e6ee5fSAndroid Build Coastguard Worker 
1437*58e6ee5fSAndroid Build Coastguard Worker 	page_map = cpu_data->page_map;
1438*58e6ee5fSAndroid Build Coastguard Worker 
1439*58e6ee5fSAndroid Build Coastguard Worker 	if (page_map && page_map->offset == map_offset)
1440*58e6ee5fSAndroid Build Coastguard Worker 		goto out;
1441*58e6ee5fSAndroid Build Coastguard Worker 
1442*58e6ee5fSAndroid Build Coastguard Worker 	list_for_each_entry(page_map, &cpu_data->page_maps, list) {
1443*58e6ee5fSAndroid Build Coastguard Worker 		if (page_map->offset == map_offset)
1444*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
1445*58e6ee5fSAndroid Build Coastguard Worker 	}
1446*58e6ee5fSAndroid Build Coastguard Worker 
1447*58e6ee5fSAndroid Build Coastguard Worker 	page_map = calloc(1, sizeof(*page_map));
1448*58e6ee5fSAndroid Build Coastguard Worker 	if (!page_map)
1449*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1450*58e6ee5fSAndroid Build Coastguard Worker 
1451*58e6ee5fSAndroid Build Coastguard Worker 	if (map_offset + map_size > cpu_data->file_offset + cpu_data->file_size)
1452*58e6ee5fSAndroid Build Coastguard Worker 		map_size -= map_offset + map_size -
1453*58e6ee5fSAndroid Build Coastguard Worker 			(cpu_data->file_offset + cpu_data->file_size);
1454*58e6ee5fSAndroid Build Coastguard Worker 
1455*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu_data->compress.fd >= 0) {
1456*58e6ee5fSAndroid Build Coastguard Worker 		map_offset -= cpu_data->file_offset;
1457*58e6ee5fSAndroid Build Coastguard Worker 		fd = cpu_data->compress.fd;
1458*58e6ee5fSAndroid Build Coastguard Worker 	} else
1459*58e6ee5fSAndroid Build Coastguard Worker 		fd = handle->fd;
1460*58e6ee5fSAndroid Build Coastguard Worker  again:
1461*58e6ee5fSAndroid Build Coastguard Worker 	page_map->size = map_size;
1462*58e6ee5fSAndroid Build Coastguard Worker 	page_map->offset = map_offset;
1463*58e6ee5fSAndroid Build Coastguard Worker 
1464*58e6ee5fSAndroid Build Coastguard Worker 	page_map->map = mmap(NULL, map_size, PROT_READ, MAP_PRIVATE, fd, map_offset);
1465*58e6ee5fSAndroid Build Coastguard Worker 
1466*58e6ee5fSAndroid Build Coastguard Worker 	if (page_map->map == MAP_FAILED) {
1467*58e6ee5fSAndroid Build Coastguard Worker 		/* Try a smaller map */
1468*58e6ee5fSAndroid Build Coastguard Worker 		map_size >>= 1;
1469*58e6ee5fSAndroid Build Coastguard Worker 		if (map_size < handle->page_size) {
1470*58e6ee5fSAndroid Build Coastguard Worker 			free(page_map);
1471*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
1472*58e6ee5fSAndroid Build Coastguard Worker 		}
1473*58e6ee5fSAndroid Build Coastguard Worker 		handle->page_map_size = map_size;
1474*58e6ee5fSAndroid Build Coastguard Worker 		map_offset = offset & ~(map_size - 1);
1475*58e6ee5fSAndroid Build Coastguard Worker 		/*
1476*58e6ee5fSAndroid Build Coastguard Worker 		 * Note, it is now possible to get duplicate memory
1477*58e6ee5fSAndroid Build Coastguard Worker 		 * maps. But that's fine, the previous maps with
1478*58e6ee5fSAndroid Build Coastguard Worker 		 * larger sizes will eventually be unmapped.
1479*58e6ee5fSAndroid Build Coastguard Worker 		 */
1480*58e6ee5fSAndroid Build Coastguard Worker 		goto again;
1481*58e6ee5fSAndroid Build Coastguard Worker 	}
1482*58e6ee5fSAndroid Build Coastguard Worker 
1483*58e6ee5fSAndroid Build Coastguard Worker 	list_add(&page_map->list, &cpu_data->page_maps);
1484*58e6ee5fSAndroid Build Coastguard Worker  out:
1485*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu_data->page_map != page_map) {
1486*58e6ee5fSAndroid Build Coastguard Worker 		struct page_map *old_map = cpu_data->page_map;
1487*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->page_map = page_map;
1488*58e6ee5fSAndroid Build Coastguard Worker 		page_map->ref_count++;
1489*58e6ee5fSAndroid Build Coastguard Worker 		if (old_map)
1490*58e6ee5fSAndroid Build Coastguard Worker 			free_page_map(old_map);
1491*58e6ee5fSAndroid Build Coastguard Worker 	}
1492*58e6ee5fSAndroid Build Coastguard Worker 	page->page_map = page_map;
1493*58e6ee5fSAndroid Build Coastguard Worker 	page_map->ref_count++;
1494*58e6ee5fSAndroid Build Coastguard Worker 	return page_map->map + offset - page_map->offset;
1495*58e6ee5fSAndroid Build Coastguard Worker }
1496*58e6ee5fSAndroid Build Coastguard Worker 
allocate_page(struct tracecmd_input * handle,int cpu,off64_t offset)1497*58e6ee5fSAndroid Build Coastguard Worker static struct page *allocate_page(struct tracecmd_input *handle,
1498*58e6ee5fSAndroid Build Coastguard Worker 				  int cpu, off64_t offset)
1499*58e6ee5fSAndroid Build Coastguard Worker {
1500*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data = &handle->cpu_data[cpu];
1501*58e6ee5fSAndroid Build Coastguard Worker 	struct page **pages;
1502*58e6ee5fSAndroid Build Coastguard Worker 	struct page *page;
1503*58e6ee5fSAndroid Build Coastguard Worker 	int index;
1504*58e6ee5fSAndroid Build Coastguard Worker 
1505*58e6ee5fSAndroid Build Coastguard Worker 	index = (offset - cpu_data->file_offset) / handle->page_size;
1506*58e6ee5fSAndroid Build Coastguard Worker 	if (index >= cpu_data->nr_pages) {
1507*58e6ee5fSAndroid Build Coastguard Worker 		pages = realloc(cpu_data->pages, (index + 1) * sizeof(*cpu_data->pages));
1508*58e6ee5fSAndroid Build Coastguard Worker 		if (!pages)
1509*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
1510*58e6ee5fSAndroid Build Coastguard Worker 		memset(pages + cpu_data->nr_pages, 0,
1511*58e6ee5fSAndroid Build Coastguard Worker 		       (index + 1 - cpu_data->nr_pages) * sizeof(*cpu_data->pages));
1512*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->pages = pages;
1513*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->nr_pages = index + 1;
1514*58e6ee5fSAndroid Build Coastguard Worker 	}
1515*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu_data->pages[index]) {
1516*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->pages[index]->ref_count++;
1517*58e6ee5fSAndroid Build Coastguard Worker 		return cpu_data->pages[index];
1518*58e6ee5fSAndroid Build Coastguard Worker 	}
1519*58e6ee5fSAndroid Build Coastguard Worker 
1520*58e6ee5fSAndroid Build Coastguard Worker 	page = malloc(sizeof(*page));
1521*58e6ee5fSAndroid Build Coastguard Worker 	if (!page)
1522*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1523*58e6ee5fSAndroid Build Coastguard Worker 
1524*58e6ee5fSAndroid Build Coastguard Worker 	memset(page, 0, sizeof(*page));
1525*58e6ee5fSAndroid Build Coastguard Worker 	page->offset = offset;
1526*58e6ee5fSAndroid Build Coastguard Worker 	page->handle = handle;
1527*58e6ee5fSAndroid Build Coastguard Worker 	page->cpu = cpu;
1528*58e6ee5fSAndroid Build Coastguard Worker 
1529*58e6ee5fSAndroid Build Coastguard Worker 	page->map = allocate_page_map(handle, page, cpu, offset);
1530*58e6ee5fSAndroid Build Coastguard Worker 
1531*58e6ee5fSAndroid Build Coastguard Worker 	if (!page->map) {
1532*58e6ee5fSAndroid Build Coastguard Worker 		free(page);
1533*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1534*58e6ee5fSAndroid Build Coastguard Worker 	}
1535*58e6ee5fSAndroid Build Coastguard Worker 
1536*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->pages[index] = page;
1537*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->page_cnt++;
1538*58e6ee5fSAndroid Build Coastguard Worker 	page->ref_count = 1;
1539*58e6ee5fSAndroid Build Coastguard Worker 
1540*58e6ee5fSAndroid Build Coastguard Worker 	return page;
1541*58e6ee5fSAndroid Build Coastguard Worker }
1542*58e6ee5fSAndroid Build Coastguard Worker 
__free_page(struct tracecmd_input * handle,struct page * page)1543*58e6ee5fSAndroid Build Coastguard Worker static void __free_page(struct tracecmd_input *handle, struct page *page)
1544*58e6ee5fSAndroid Build Coastguard Worker {
1545*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data = &handle->cpu_data[page->cpu];
1546*58e6ee5fSAndroid Build Coastguard Worker 	struct page **pages;
1547*58e6ee5fSAndroid Build Coastguard Worker 	int index;
1548*58e6ee5fSAndroid Build Coastguard Worker 
1549*58e6ee5fSAndroid Build Coastguard Worker 	if (!page->ref_count) {
1550*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_critical("Page ref count is zero!");
1551*58e6ee5fSAndroid Build Coastguard Worker 		return;
1552*58e6ee5fSAndroid Build Coastguard Worker 	}
1553*58e6ee5fSAndroid Build Coastguard Worker 
1554*58e6ee5fSAndroid Build Coastguard Worker 	page->ref_count--;
1555*58e6ee5fSAndroid Build Coastguard Worker 	if (page->ref_count)
1556*58e6ee5fSAndroid Build Coastguard Worker 		return;
1557*58e6ee5fSAndroid Build Coastguard Worker 
1558*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->read_page)
1559*58e6ee5fSAndroid Build Coastguard Worker 		free(page->map);
1560*58e6ee5fSAndroid Build Coastguard Worker 	else if (handle->read_zpage)
1561*58e6ee5fSAndroid Build Coastguard Worker 		free_zpage(cpu_data, page->map);
1562*58e6ee5fSAndroid Build Coastguard Worker 	else
1563*58e6ee5fSAndroid Build Coastguard Worker 		free_page_map(page->page_map);
1564*58e6ee5fSAndroid Build Coastguard Worker 
1565*58e6ee5fSAndroid Build Coastguard Worker 	index = (page->offset - cpu_data->file_offset) / handle->page_size;
1566*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->pages[index] = NULL;
1567*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->page_cnt--;
1568*58e6ee5fSAndroid Build Coastguard Worker 
1569*58e6ee5fSAndroid Build Coastguard Worker 	free(page);
1570*58e6ee5fSAndroid Build Coastguard Worker 
1571*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->use_pipe) {
1572*58e6ee5fSAndroid Build Coastguard Worker 		for (index = cpu_data->nr_pages - 1; index > 0; index--)
1573*58e6ee5fSAndroid Build Coastguard Worker 			if (cpu_data->pages[index])
1574*58e6ee5fSAndroid Build Coastguard Worker 				break;
1575*58e6ee5fSAndroid Build Coastguard Worker 		if (index < (cpu_data->nr_pages - 1)) {
1576*58e6ee5fSAndroid Build Coastguard Worker 			pages = realloc(cpu_data->pages, (index + 1) * sizeof(*cpu_data->pages));
1577*58e6ee5fSAndroid Build Coastguard Worker 			if (!pages)
1578*58e6ee5fSAndroid Build Coastguard Worker 				return;
1579*58e6ee5fSAndroid Build Coastguard Worker 			cpu_data->pages = pages;
1580*58e6ee5fSAndroid Build Coastguard Worker 			cpu_data->nr_pages = index + 1;
1581*58e6ee5fSAndroid Build Coastguard Worker 		}
1582*58e6ee5fSAndroid Build Coastguard Worker 	}
1583*58e6ee5fSAndroid Build Coastguard Worker }
1584*58e6ee5fSAndroid Build Coastguard Worker 
free_page(struct tracecmd_input * handle,int cpu)1585*58e6ee5fSAndroid Build Coastguard Worker static void free_page(struct tracecmd_input *handle, int cpu)
1586*58e6ee5fSAndroid Build Coastguard Worker {
1587*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->cpu_data || cpu >= handle->cpus ||
1588*58e6ee5fSAndroid Build Coastguard Worker 	    !handle->cpu_data[cpu].page)
1589*58e6ee5fSAndroid Build Coastguard Worker 		return;
1590*58e6ee5fSAndroid Build Coastguard Worker 
1591*58e6ee5fSAndroid Build Coastguard Worker 	__free_page(handle, handle->cpu_data[cpu].page);
1592*58e6ee5fSAndroid Build Coastguard Worker 
1593*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].page = NULL;
1594*58e6ee5fSAndroid Build Coastguard Worker }
1595*58e6ee5fSAndroid Build Coastguard Worker 
__free_record(struct tep_record * record)1596*58e6ee5fSAndroid Build Coastguard Worker static void __free_record(struct tep_record *record)
1597*58e6ee5fSAndroid Build Coastguard Worker {
1598*58e6ee5fSAndroid Build Coastguard Worker 	if (record->priv) {
1599*58e6ee5fSAndroid Build Coastguard Worker 		struct page *page = record->priv;
1600*58e6ee5fSAndroid Build Coastguard Worker 		remove_record(page, record);
1601*58e6ee5fSAndroid Build Coastguard Worker 		__free_page(page->handle, page);
1602*58e6ee5fSAndroid Build Coastguard Worker 	}
1603*58e6ee5fSAndroid Build Coastguard Worker 
1604*58e6ee5fSAndroid Build Coastguard Worker 	free(record);
1605*58e6ee5fSAndroid Build Coastguard Worker }
1606*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_free_record(struct tep_record * record)1607*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_free_record(struct tep_record *record)
1608*58e6ee5fSAndroid Build Coastguard Worker {
1609*58e6ee5fSAndroid Build Coastguard Worker 	if (!record)
1610*58e6ee5fSAndroid Build Coastguard Worker 		return;
1611*58e6ee5fSAndroid Build Coastguard Worker 
1612*58e6ee5fSAndroid Build Coastguard Worker 	if (!record->ref_count) {
1613*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_critical("record ref count is zero!");
1614*58e6ee5fSAndroid Build Coastguard Worker 		return;
1615*58e6ee5fSAndroid Build Coastguard Worker 	}
1616*58e6ee5fSAndroid Build Coastguard Worker 
1617*58e6ee5fSAndroid Build Coastguard Worker 	record->ref_count--;
1618*58e6ee5fSAndroid Build Coastguard Worker 
1619*58e6ee5fSAndroid Build Coastguard Worker 	if (record->ref_count)
1620*58e6ee5fSAndroid Build Coastguard Worker 		return;
1621*58e6ee5fSAndroid Build Coastguard Worker 
1622*58e6ee5fSAndroid Build Coastguard Worker 	if (record->locked) {
1623*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_critical("freeing record when it is locked!");
1624*58e6ee5fSAndroid Build Coastguard Worker 		return;
1625*58e6ee5fSAndroid Build Coastguard Worker 	}
1626*58e6ee5fSAndroid Build Coastguard Worker 
1627*58e6ee5fSAndroid Build Coastguard Worker 	record->data = NULL;
1628*58e6ee5fSAndroid Build Coastguard Worker 
1629*58e6ee5fSAndroid Build Coastguard Worker 	__free_record(record);
1630*58e6ee5fSAndroid Build Coastguard Worker }
1631*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_record_ref(struct tep_record * record)1632*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_record_ref(struct tep_record *record)
1633*58e6ee5fSAndroid Build Coastguard Worker {
1634*58e6ee5fSAndroid Build Coastguard Worker 	record->ref_count++;
1635*58e6ee5fSAndroid Build Coastguard Worker #if DEBUG_RECORD
1636*58e6ee5fSAndroid Build Coastguard Worker 	/* Update locating of last reference */
1637*58e6ee5fSAndroid Build Coastguard Worker 	record->alloc_addr = (unsigned long)__builtin_return_address(0);
1638*58e6ee5fSAndroid Build Coastguard Worker #endif
1639*58e6ee5fSAndroid Build Coastguard Worker }
1640*58e6ee5fSAndroid Build Coastguard Worker 
free_next(struct tracecmd_input * handle,int cpu)1641*58e6ee5fSAndroid Build Coastguard Worker static void free_next(struct tracecmd_input *handle, int cpu)
1642*58e6ee5fSAndroid Build Coastguard Worker {
1643*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record;
1644*58e6ee5fSAndroid Build Coastguard Worker 
1645*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->cpu_data || cpu >= handle->cpus)
1646*58e6ee5fSAndroid Build Coastguard Worker 		return;
1647*58e6ee5fSAndroid Build Coastguard Worker 
1648*58e6ee5fSAndroid Build Coastguard Worker 	record = handle->cpu_data[cpu].next;
1649*58e6ee5fSAndroid Build Coastguard Worker 	if (!record)
1650*58e6ee5fSAndroid Build Coastguard Worker 		return;
1651*58e6ee5fSAndroid Build Coastguard Worker 
1652*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].next = NULL;
1653*58e6ee5fSAndroid Build Coastguard Worker 
1654*58e6ee5fSAndroid Build Coastguard Worker 	record->locked = 0;
1655*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_free_record(record);
1656*58e6ee5fSAndroid Build Coastguard Worker }
1657*58e6ee5fSAndroid Build Coastguard Worker 
1658*58e6ee5fSAndroid Build Coastguard Worker /* This functions was taken from the Linux kernel */
mul_u64_u32_shr(unsigned long long a,unsigned long long mul,unsigned int shift)1659*58e6ee5fSAndroid Build Coastguard Worker static unsigned long long mul_u64_u32_shr(unsigned long long a,
1660*58e6ee5fSAndroid Build Coastguard Worker 					  unsigned long long mul, unsigned int shift)
1661*58e6ee5fSAndroid Build Coastguard Worker {
1662*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int ah, al;
1663*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long ret;
1664*58e6ee5fSAndroid Build Coastguard Worker 
1665*58e6ee5fSAndroid Build Coastguard Worker 	al = a;
1666*58e6ee5fSAndroid Build Coastguard Worker 	ah = a >> 32;
1667*58e6ee5fSAndroid Build Coastguard Worker 
1668*58e6ee5fSAndroid Build Coastguard Worker 	ret = (al * mul) >> shift;
1669*58e6ee5fSAndroid Build Coastguard Worker 	if (ah)
1670*58e6ee5fSAndroid Build Coastguard Worker 		ret += (ah * mul) << (32 - shift);
1671*58e6ee5fSAndroid Build Coastguard Worker 
1672*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
1673*58e6ee5fSAndroid Build Coastguard Worker }
1674*58e6ee5fSAndroid Build Coastguard Worker 
1675*58e6ee5fSAndroid Build Coastguard Worker static inline unsigned long long
timestamp_correction_calc(unsigned long long ts,unsigned int flags,struct ts_offset_sample * min,struct ts_offset_sample * max)1676*58e6ee5fSAndroid Build Coastguard Worker timestamp_correction_calc(unsigned long long ts, unsigned int flags,
1677*58e6ee5fSAndroid Build Coastguard Worker 			  struct ts_offset_sample *min,
1678*58e6ee5fSAndroid Build Coastguard Worker 			  struct ts_offset_sample *max)
1679*58e6ee5fSAndroid Build Coastguard Worker {
1680*58e6ee5fSAndroid Build Coastguard Worker 	long long tscor;
1681*58e6ee5fSAndroid Build Coastguard Worker 
1682*58e6ee5fSAndroid Build Coastguard Worker 	if (flags & TRACECMD_TSYNC_FLAG_INTERPOLATE) {
1683*58e6ee5fSAndroid Build Coastguard Worker 		long long delta = max->time - min->time;
1684*58e6ee5fSAndroid Build Coastguard Worker 		long long offset = ((long long)ts - min->time) *
1685*58e6ee5fSAndroid Build Coastguard Worker 				   (max->offset - min->offset);
1686*58e6ee5fSAndroid Build Coastguard Worker 
1687*58e6ee5fSAndroid Build Coastguard Worker 		tscor = min->offset + (offset + delta / 2) / delta;
1688*58e6ee5fSAndroid Build Coastguard Worker 	} else {
1689*58e6ee5fSAndroid Build Coastguard Worker 		tscor = min->offset;
1690*58e6ee5fSAndroid Build Coastguard Worker 	}
1691*58e6ee5fSAndroid Build Coastguard Worker 
1692*58e6ee5fSAndroid Build Coastguard Worker 	ts = (ts * min->scaling) >> min->fraction;
1693*58e6ee5fSAndroid Build Coastguard Worker 	if (tscor < 0)
1694*58e6ee5fSAndroid Build Coastguard Worker 		return ts - llabs(tscor);
1695*58e6ee5fSAndroid Build Coastguard Worker 
1696*58e6ee5fSAndroid Build Coastguard Worker 	return ts + tscor;
1697*58e6ee5fSAndroid Build Coastguard Worker }
1698*58e6ee5fSAndroid Build Coastguard Worker 
timestamp_host_sync(unsigned long long ts,int cpu,struct tracecmd_input * handle)1699*58e6ee5fSAndroid Build Coastguard Worker static unsigned long long timestamp_host_sync(unsigned long long ts, int cpu,
1700*58e6ee5fSAndroid Build Coastguard Worker 					      struct tracecmd_input *handle)
1701*58e6ee5fSAndroid Build Coastguard Worker {
1702*58e6ee5fSAndroid Build Coastguard Worker 	struct timesync_offsets *tsync;
1703*58e6ee5fSAndroid Build Coastguard Worker 	int min, mid, max;
1704*58e6ee5fSAndroid Build Coastguard Worker 
1705*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu >= handle->host.cpu_count)
1706*58e6ee5fSAndroid Build Coastguard Worker 		return ts;
1707*58e6ee5fSAndroid Build Coastguard Worker 	tsync = &handle->host.ts_offsets[cpu];
1708*58e6ee5fSAndroid Build Coastguard Worker 
1709*58e6ee5fSAndroid Build Coastguard Worker 	/* We have one sample, nothing to calc here */
1710*58e6ee5fSAndroid Build Coastguard Worker 	if (tsync->ts_samples_count == 1)
1711*58e6ee5fSAndroid Build Coastguard Worker 		return ts + tsync->ts_samples[0].offset;
1712*58e6ee5fSAndroid Build Coastguard Worker 
1713*58e6ee5fSAndroid Build Coastguard Worker 	/* We have two samples, nothing to search here */
1714*58e6ee5fSAndroid Build Coastguard Worker 	if (tsync->ts_samples_count == 2)
1715*58e6ee5fSAndroid Build Coastguard Worker 		return timestamp_correction_calc(ts, handle->host.flags,
1716*58e6ee5fSAndroid Build Coastguard Worker 						 &tsync->ts_samples[0],
1717*58e6ee5fSAndroid Build Coastguard Worker 						 &tsync->ts_samples[1]);
1718*58e6ee5fSAndroid Build Coastguard Worker 
1719*58e6ee5fSAndroid Build Coastguard Worker 	/* We have more than two samples */
1720*58e6ee5fSAndroid Build Coastguard Worker 	if (ts <= tsync->ts_samples[0].time)
1721*58e6ee5fSAndroid Build Coastguard Worker 		return timestamp_correction_calc(ts, handle->host.flags,
1722*58e6ee5fSAndroid Build Coastguard Worker 						 &tsync->ts_samples[0],
1723*58e6ee5fSAndroid Build Coastguard Worker 						 &tsync->ts_samples[1]);
1724*58e6ee5fSAndroid Build Coastguard Worker 	else if (ts >= tsync->ts_samples[tsync->ts_samples_count-1].time)
1725*58e6ee5fSAndroid Build Coastguard Worker 		return timestamp_correction_calc(ts, handle->host.flags,
1726*58e6ee5fSAndroid Build Coastguard Worker 						 &tsync->ts_samples[tsync->ts_samples_count-2],
1727*58e6ee5fSAndroid Build Coastguard Worker 						 &tsync->ts_samples[tsync->ts_samples_count-1]);
1728*58e6ee5fSAndroid Build Coastguard Worker 	min = 0;
1729*58e6ee5fSAndroid Build Coastguard Worker 	max = tsync->ts_samples_count-1;
1730*58e6ee5fSAndroid Build Coastguard Worker 	mid = (min + max)/2;
1731*58e6ee5fSAndroid Build Coastguard Worker 	while (min <= max) {
1732*58e6ee5fSAndroid Build Coastguard Worker 		if (ts < tsync->ts_samples[mid].time)
1733*58e6ee5fSAndroid Build Coastguard Worker 			max = mid - 1;
1734*58e6ee5fSAndroid Build Coastguard Worker 		else if (ts > tsync->ts_samples[mid].time)
1735*58e6ee5fSAndroid Build Coastguard Worker 			min = mid + 1;
1736*58e6ee5fSAndroid Build Coastguard Worker 		else
1737*58e6ee5fSAndroid Build Coastguard Worker 			break;
1738*58e6ee5fSAndroid Build Coastguard Worker 		mid = (min + max)/2;
1739*58e6ee5fSAndroid Build Coastguard Worker 	}
1740*58e6ee5fSAndroid Build Coastguard Worker 
1741*58e6ee5fSAndroid Build Coastguard Worker 	return timestamp_correction_calc(ts, handle->host.flags,
1742*58e6ee5fSAndroid Build Coastguard Worker 					 &tsync->ts_samples[mid],
1743*58e6ee5fSAndroid Build Coastguard Worker 					 &tsync->ts_samples[mid+1]);
1744*58e6ee5fSAndroid Build Coastguard Worker }
1745*58e6ee5fSAndroid Build Coastguard Worker 
timestamp_calc(unsigned long long ts,int cpu,struct tracecmd_input * handle)1746*58e6ee5fSAndroid Build Coastguard Worker static unsigned long long timestamp_calc(unsigned long long ts, int cpu,
1747*58e6ee5fSAndroid Build Coastguard Worker 					 struct tracecmd_input *handle)
1748*58e6ee5fSAndroid Build Coastguard Worker {
1749*58e6ee5fSAndroid Build Coastguard Worker 	/* do not modify raw timestamps */
1750*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->flags & TRACECMD_FL_RAW_TS)
1751*58e6ee5fSAndroid Build Coastguard Worker 		return ts;
1752*58e6ee5fSAndroid Build Coastguard Worker 
1753*58e6ee5fSAndroid Build Coastguard Worker 	/* Guest trace file, sync with host timestamps */
1754*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->host.sync_enable)
1755*58e6ee5fSAndroid Build Coastguard Worker 		ts = timestamp_host_sync(ts, cpu, handle);
1756*58e6ee5fSAndroid Build Coastguard Worker 
1757*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->ts2secs) {
1758*58e6ee5fSAndroid Build Coastguard Worker 		/* user specified clock frequency */
1759*58e6ee5fSAndroid Build Coastguard Worker 		ts *= handle->ts2secs;
1760*58e6ee5fSAndroid Build Coastguard Worker 	} else if (handle->tsc_calc.mult) {
1761*58e6ee5fSAndroid Build Coastguard Worker 		/* auto calculated TSC clock frequency */
1762*58e6ee5fSAndroid Build Coastguard Worker 		ts = mul_u64_u32_shr(ts, handle->tsc_calc.mult, handle->tsc_calc.shift);
1763*58e6ee5fSAndroid Build Coastguard Worker 	}
1764*58e6ee5fSAndroid Build Coastguard Worker 
1765*58e6ee5fSAndroid Build Coastguard Worker 	/* User specified time offset with --ts-offset or --date options */
1766*58e6ee5fSAndroid Build Coastguard Worker 	ts += handle->ts_offset;
1767*58e6ee5fSAndroid Build Coastguard Worker 
1768*58e6ee5fSAndroid Build Coastguard Worker 	return ts;
1769*58e6ee5fSAndroid Build Coastguard Worker }
1770*58e6ee5fSAndroid Build Coastguard Worker 
1771*58e6ee5fSAndroid Build Coastguard Worker /*
1772*58e6ee5fSAndroid Build Coastguard Worker  * Page is mapped, now read in the page header info.
1773*58e6ee5fSAndroid Build Coastguard Worker  */
update_page_info(struct tracecmd_input * handle,int cpu)1774*58e6ee5fSAndroid Build Coastguard Worker static int update_page_info(struct tracecmd_input *handle, int cpu)
1775*58e6ee5fSAndroid Build Coastguard Worker {
1776*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = handle->pevent;
1777*58e6ee5fSAndroid Build Coastguard Worker 	void *ptr = handle->cpu_data[cpu].page->map;
1778*58e6ee5fSAndroid Build Coastguard Worker 	struct kbuffer *kbuf = handle->cpu_data[cpu].kbuf;
1779*58e6ee5fSAndroid Build Coastguard Worker 
1780*58e6ee5fSAndroid Build Coastguard Worker 	/* FIXME: handle header page */
1781*58e6ee5fSAndroid Build Coastguard Worker 	if (tep_get_header_timestamp_size(pevent) != 8) {
1782*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_warning("expected a long long type for timestamp");
1783*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1784*58e6ee5fSAndroid Build Coastguard Worker 	}
1785*58e6ee5fSAndroid Build Coastguard Worker 
1786*58e6ee5fSAndroid Build Coastguard Worker 	kbuffer_load_subbuffer(kbuf, ptr);
1787*58e6ee5fSAndroid Build Coastguard Worker 	if (kbuffer_subbuffer_size(kbuf) > handle->page_size) {
1788*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_warning("bad page read, with size of %d", kbuffer_subbuffer_size(kbuf));
1789*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1790*58e6ee5fSAndroid Build Coastguard Worker 	}
1791*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].timestamp = timestamp_calc(kbuffer_timestamp(kbuf),
1792*58e6ee5fSAndroid Build Coastguard Worker 							 cpu, handle);
1793*58e6ee5fSAndroid Build Coastguard Worker 
1794*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1795*58e6ee5fSAndroid Build Coastguard Worker }
1796*58e6ee5fSAndroid Build Coastguard Worker 
1797*58e6ee5fSAndroid Build Coastguard Worker /*
1798*58e6ee5fSAndroid Build Coastguard Worker  * get_page maps a page for a given cpu.
1799*58e6ee5fSAndroid Build Coastguard Worker  *
1800*58e6ee5fSAndroid Build Coastguard Worker  * Returns 1 if the page was already mapped,
1801*58e6ee5fSAndroid Build Coastguard Worker  *         0 if it mapped successfully
1802*58e6ee5fSAndroid Build Coastguard Worker  *        -1 on error
1803*58e6ee5fSAndroid Build Coastguard Worker  */
get_page(struct tracecmd_input * handle,int cpu,off64_t offset)1804*58e6ee5fSAndroid Build Coastguard Worker static int get_page(struct tracecmd_input *handle, int cpu,
1805*58e6ee5fSAndroid Build Coastguard Worker 		    off64_t offset)
1806*58e6ee5fSAndroid Build Coastguard Worker {
1807*58e6ee5fSAndroid Build Coastguard Worker 	/* Don't map if the page is already where we want */
1808*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->cpu_data[cpu].offset == offset &&
1809*58e6ee5fSAndroid Build Coastguard Worker 	    handle->cpu_data[cpu].page)
1810*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
1811*58e6ee5fSAndroid Build Coastguard Worker 
1812*58e6ee5fSAndroid Build Coastguard Worker 	/* Do not map no data for CPU */
1813*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->cpu_data[cpu].size)
1814*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1815*58e6ee5fSAndroid Build Coastguard Worker 
1816*58e6ee5fSAndroid Build Coastguard Worker 	if (offset & (handle->page_size - 1)) {
1817*58e6ee5fSAndroid Build Coastguard Worker 		errno = -EINVAL;
1818*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_critical("bad page offset %llx", offset);
1819*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1820*58e6ee5fSAndroid Build Coastguard Worker 	}
1821*58e6ee5fSAndroid Build Coastguard Worker 
1822*58e6ee5fSAndroid Build Coastguard Worker 	if (offset < handle->cpu_data[cpu].file_offset ||
1823*58e6ee5fSAndroid Build Coastguard Worker 	    offset > handle->cpu_data[cpu].file_offset +
1824*58e6ee5fSAndroid Build Coastguard Worker 	    handle->cpu_data[cpu].file_size) {
1825*58e6ee5fSAndroid Build Coastguard Worker 		errno = -EINVAL;
1826*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_critical("bad page offset %llx", offset);
1827*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1828*58e6ee5fSAndroid Build Coastguard Worker 	}
1829*58e6ee5fSAndroid Build Coastguard Worker 
1830*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].offset = offset;
1831*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].size = (handle->cpu_data[cpu].file_offset +
1832*58e6ee5fSAndroid Build Coastguard Worker 				      handle->cpu_data[cpu].file_size) -
1833*58e6ee5fSAndroid Build Coastguard Worker 					offset;
1834*58e6ee5fSAndroid Build Coastguard Worker 
1835*58e6ee5fSAndroid Build Coastguard Worker 	free_page(handle, cpu);
1836*58e6ee5fSAndroid Build Coastguard Worker 
1837*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].page = allocate_page(handle, cpu, offset);
1838*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->cpu_data[cpu].page)
1839*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1840*58e6ee5fSAndroid Build Coastguard Worker 
1841*58e6ee5fSAndroid Build Coastguard Worker 	if (update_page_info(handle, cpu))
1842*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1843*58e6ee5fSAndroid Build Coastguard Worker 
1844*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1845*58e6ee5fSAndroid Build Coastguard Worker }
1846*58e6ee5fSAndroid Build Coastguard Worker 
get_next_page(struct tracecmd_input * handle,int cpu)1847*58e6ee5fSAndroid Build Coastguard Worker static int get_next_page(struct tracecmd_input *handle, int cpu)
1848*58e6ee5fSAndroid Build Coastguard Worker {
1849*58e6ee5fSAndroid Build Coastguard Worker 	off64_t offset;
1850*58e6ee5fSAndroid Build Coastguard Worker 
1851*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->cpu_data[cpu].page && !handle->use_pipe)
1852*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1853*58e6ee5fSAndroid Build Coastguard Worker 
1854*58e6ee5fSAndroid Build Coastguard Worker 	free_page(handle, cpu);
1855*58e6ee5fSAndroid Build Coastguard Worker 
1856*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->cpu_data[cpu].size <= handle->page_size) {
1857*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data[cpu].offset = 0;
1858*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1859*58e6ee5fSAndroid Build Coastguard Worker 	}
1860*58e6ee5fSAndroid Build Coastguard Worker 
1861*58e6ee5fSAndroid Build Coastguard Worker 	offset = handle->cpu_data[cpu].offset + handle->page_size;
1862*58e6ee5fSAndroid Build Coastguard Worker 
1863*58e6ee5fSAndroid Build Coastguard Worker 	return get_page(handle, cpu, offset);
1864*58e6ee5fSAndroid Build Coastguard Worker }
1865*58e6ee5fSAndroid Build Coastguard Worker 
1866*58e6ee5fSAndroid Build Coastguard Worker static struct tep_record *
peek_event(struct tracecmd_input * handle,unsigned long long offset,int cpu)1867*58e6ee5fSAndroid Build Coastguard Worker peek_event(struct tracecmd_input *handle, unsigned long long offset,
1868*58e6ee5fSAndroid Build Coastguard Worker 	   int cpu)
1869*58e6ee5fSAndroid Build Coastguard Worker {
1870*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record = NULL;
1871*58e6ee5fSAndroid Build Coastguard Worker 
1872*58e6ee5fSAndroid Build Coastguard Worker 	/*
1873*58e6ee5fSAndroid Build Coastguard Worker 	 * Since the timestamp is calculated from the beginning
1874*58e6ee5fSAndroid Build Coastguard Worker 	 * of the page and through each event, we reset the
1875*58e6ee5fSAndroid Build Coastguard Worker 	 * page to the beginning. This is just used by
1876*58e6ee5fSAndroid Build Coastguard Worker 	 * tracecmd_read_at.
1877*58e6ee5fSAndroid Build Coastguard Worker 	 */
1878*58e6ee5fSAndroid Build Coastguard Worker 	update_page_info(handle, cpu);
1879*58e6ee5fSAndroid Build Coastguard Worker 
1880*58e6ee5fSAndroid Build Coastguard Worker 	do {
1881*58e6ee5fSAndroid Build Coastguard Worker 		free_next(handle, cpu);
1882*58e6ee5fSAndroid Build Coastguard Worker 		record = tracecmd_peek_data(handle, cpu);
1883*58e6ee5fSAndroid Build Coastguard Worker 		if (record && (record->offset + record->record_size) > offset)
1884*58e6ee5fSAndroid Build Coastguard Worker 			break;
1885*58e6ee5fSAndroid Build Coastguard Worker         } while (record);
1886*58e6ee5fSAndroid Build Coastguard Worker 
1887*58e6ee5fSAndroid Build Coastguard Worker 	return record;
1888*58e6ee5fSAndroid Build Coastguard Worker }
1889*58e6ee5fSAndroid Build Coastguard Worker 
1890*58e6ee5fSAndroid Build Coastguard Worker static struct tep_record *
read_event(struct tracecmd_input * handle,unsigned long long offset,int cpu)1891*58e6ee5fSAndroid Build Coastguard Worker read_event(struct tracecmd_input *handle, unsigned long long offset,
1892*58e6ee5fSAndroid Build Coastguard Worker 	   int cpu)
1893*58e6ee5fSAndroid Build Coastguard Worker {
1894*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record;
1895*58e6ee5fSAndroid Build Coastguard Worker 
1896*58e6ee5fSAndroid Build Coastguard Worker 	record = peek_event(handle, offset, cpu);
1897*58e6ee5fSAndroid Build Coastguard Worker 	if (record)
1898*58e6ee5fSAndroid Build Coastguard Worker 		record = tracecmd_read_data(handle, cpu);
1899*58e6ee5fSAndroid Build Coastguard Worker 	return record;
1900*58e6ee5fSAndroid Build Coastguard Worker }
1901*58e6ee5fSAndroid Build Coastguard Worker 
1902*58e6ee5fSAndroid Build Coastguard Worker static struct tep_record *
find_and_peek_event(struct tracecmd_input * handle,unsigned long long offset,int * pcpu)1903*58e6ee5fSAndroid Build Coastguard Worker find_and_peek_event(struct tracecmd_input *handle, unsigned long long offset,
1904*58e6ee5fSAndroid Build Coastguard Worker 		    int *pcpu)
1905*58e6ee5fSAndroid Build Coastguard Worker {
1906*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long page_offset;
1907*58e6ee5fSAndroid Build Coastguard Worker 	int cpu;
1908*58e6ee5fSAndroid Build Coastguard Worker 
1909*58e6ee5fSAndroid Build Coastguard Worker 	/* find the cpu that this offset exists in */
1910*58e6ee5fSAndroid Build Coastguard Worker 	for (cpu = 0; cpu < handle->cpus; cpu++) {
1911*58e6ee5fSAndroid Build Coastguard Worker 		if (offset >= handle->cpu_data[cpu].file_offset &&
1912*58e6ee5fSAndroid Build Coastguard Worker 		    offset < handle->cpu_data[cpu].file_offset +
1913*58e6ee5fSAndroid Build Coastguard Worker 		    handle->cpu_data[cpu].file_size)
1914*58e6ee5fSAndroid Build Coastguard Worker 			break;
1915*58e6ee5fSAndroid Build Coastguard Worker 	}
1916*58e6ee5fSAndroid Build Coastguard Worker 
1917*58e6ee5fSAndroid Build Coastguard Worker 	/* Not found? */
1918*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu == handle->cpus)
1919*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1920*58e6ee5fSAndroid Build Coastguard Worker 
1921*58e6ee5fSAndroid Build Coastguard Worker 	/* Move this cpu index to point to this offest */
1922*58e6ee5fSAndroid Build Coastguard Worker 	page_offset = calc_page_offset(handle, offset);
1923*58e6ee5fSAndroid Build Coastguard Worker 
1924*58e6ee5fSAndroid Build Coastguard Worker 	if (get_page(handle, cpu, page_offset) < 0)
1925*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1926*58e6ee5fSAndroid Build Coastguard Worker 
1927*58e6ee5fSAndroid Build Coastguard Worker 	if (pcpu)
1928*58e6ee5fSAndroid Build Coastguard Worker 		*pcpu = cpu;
1929*58e6ee5fSAndroid Build Coastguard Worker 
1930*58e6ee5fSAndroid Build Coastguard Worker 	return peek_event(handle, offset, cpu);
1931*58e6ee5fSAndroid Build Coastguard Worker }
1932*58e6ee5fSAndroid Build Coastguard Worker 
1933*58e6ee5fSAndroid Build Coastguard Worker 
1934*58e6ee5fSAndroid Build Coastguard Worker static struct tep_record *
find_and_read_event(struct tracecmd_input * handle,unsigned long long offset,int * pcpu)1935*58e6ee5fSAndroid Build Coastguard Worker find_and_read_event(struct tracecmd_input *handle, unsigned long long offset,
1936*58e6ee5fSAndroid Build Coastguard Worker 		    int *pcpu)
1937*58e6ee5fSAndroid Build Coastguard Worker {
1938*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record;
1939*58e6ee5fSAndroid Build Coastguard Worker 	int cpu;
1940*58e6ee5fSAndroid Build Coastguard Worker 
1941*58e6ee5fSAndroid Build Coastguard Worker 	record = find_and_peek_event(handle, offset, &cpu);
1942*58e6ee5fSAndroid Build Coastguard Worker 	if (record) {
1943*58e6ee5fSAndroid Build Coastguard Worker 		record = tracecmd_read_data(handle, cpu);
1944*58e6ee5fSAndroid Build Coastguard Worker 		if (pcpu)
1945*58e6ee5fSAndroid Build Coastguard Worker 			*pcpu = cpu;
1946*58e6ee5fSAndroid Build Coastguard Worker 	}
1947*58e6ee5fSAndroid Build Coastguard Worker 	return record;
1948*58e6ee5fSAndroid Build Coastguard Worker }
1949*58e6ee5fSAndroid Build Coastguard Worker 
1950*58e6ee5fSAndroid Build Coastguard Worker /**
1951*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_read_at - read a record from a specific offset
1952*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
1953*58e6ee5fSAndroid Build Coastguard Worker  * @offset: the offset into the file to find the record
1954*58e6ee5fSAndroid Build Coastguard Worker  * @pcpu: pointer to a variable to store the CPU id the record was found in
1955*58e6ee5fSAndroid Build Coastguard Worker  *
1956*58e6ee5fSAndroid Build Coastguard Worker  * This function is useful when looking for a previous record.
1957*58e6ee5fSAndroid Build Coastguard Worker  * You can store the offset of the record "record->offset" and use that
1958*58e6ee5fSAndroid Build Coastguard Worker  * offset to retreive the record again without needing to store any
1959*58e6ee5fSAndroid Build Coastguard Worker  * other information about the record.
1960*58e6ee5fSAndroid Build Coastguard Worker  *
1961*58e6ee5fSAndroid Build Coastguard Worker  * The record returned must be freed.
1962*58e6ee5fSAndroid Build Coastguard Worker  */
1963*58e6ee5fSAndroid Build Coastguard Worker struct tep_record *
tracecmd_read_at(struct tracecmd_input * handle,unsigned long long offset,int * pcpu)1964*58e6ee5fSAndroid Build Coastguard Worker tracecmd_read_at(struct tracecmd_input *handle, unsigned long long offset,
1965*58e6ee5fSAndroid Build Coastguard Worker 		 int *pcpu)
1966*58e6ee5fSAndroid Build Coastguard Worker {
1967*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long page_offset;
1968*58e6ee5fSAndroid Build Coastguard Worker 	int cpu;
1969*58e6ee5fSAndroid Build Coastguard Worker 
1970*58e6ee5fSAndroid Build Coastguard Worker 	page_offset = calc_page_offset(handle, offset);
1971*58e6ee5fSAndroid Build Coastguard Worker 
1972*58e6ee5fSAndroid Build Coastguard Worker 	/* check to see if we have this page already */
1973*58e6ee5fSAndroid Build Coastguard Worker 	for (cpu = 0; cpu < handle->cpus; cpu++) {
1974*58e6ee5fSAndroid Build Coastguard Worker 		if (handle->cpu_data[cpu].offset == page_offset &&
1975*58e6ee5fSAndroid Build Coastguard Worker 		    handle->cpu_data[cpu].file_size)
1976*58e6ee5fSAndroid Build Coastguard Worker 			break;
1977*58e6ee5fSAndroid Build Coastguard Worker 	}
1978*58e6ee5fSAndroid Build Coastguard Worker 
1979*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu < handle->cpus && handle->cpu_data[cpu].page) {
1980*58e6ee5fSAndroid Build Coastguard Worker 		if (pcpu)
1981*58e6ee5fSAndroid Build Coastguard Worker 			*pcpu = cpu;
1982*58e6ee5fSAndroid Build Coastguard Worker 		return read_event(handle, offset, cpu);
1983*58e6ee5fSAndroid Build Coastguard Worker 	} else
1984*58e6ee5fSAndroid Build Coastguard Worker 		return find_and_read_event(handle, offset, pcpu);
1985*58e6ee5fSAndroid Build Coastguard Worker }
1986*58e6ee5fSAndroid Build Coastguard Worker 
1987*58e6ee5fSAndroid Build Coastguard Worker /**
1988*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_refresh_record - remaps the records data
1989*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
1990*58e6ee5fSAndroid Build Coastguard Worker  * @record: the record to be refreshed
1991*58e6ee5fSAndroid Build Coastguard Worker  *
1992*58e6ee5fSAndroid Build Coastguard Worker  * A record data points to a mmap section of memory.
1993*58e6ee5fSAndroid Build Coastguard Worker  * by reading new records the mmap section may be unmapped.
1994*58e6ee5fSAndroid Build Coastguard Worker  * This will refresh the record's data mapping.
1995*58e6ee5fSAndroid Build Coastguard Worker  *
1996*58e6ee5fSAndroid Build Coastguard Worker  * ===== OBSOLETED BY PAGE REFERENCES =====
1997*58e6ee5fSAndroid Build Coastguard Worker  *
1998*58e6ee5fSAndroid Build Coastguard Worker  * Returns 1 if page is still mapped (does not modify CPU iterator)
1999*58e6ee5fSAndroid Build Coastguard Worker  *         0 on successful mapping (was not mapped before,
2000*58e6ee5fSAndroid Build Coastguard Worker  *                      This will update CPU iterator to point to
2001*58e6ee5fSAndroid Build Coastguard Worker  *                      the next record)
2002*58e6ee5fSAndroid Build Coastguard Worker  *        -1 on error.
2003*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_refresh_record(struct tracecmd_input * handle,struct tep_record * record)2004*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_refresh_record(struct tracecmd_input *handle,
2005*58e6ee5fSAndroid Build Coastguard Worker 			    struct tep_record *record)
2006*58e6ee5fSAndroid Build Coastguard Worker {
2007*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long page_offset;
2008*58e6ee5fSAndroid Build Coastguard Worker 	int cpu = record->cpu;
2009*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data = &handle->cpu_data[cpu];
2010*58e6ee5fSAndroid Build Coastguard Worker 	int index;
2011*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
2012*58e6ee5fSAndroid Build Coastguard Worker 
2013*58e6ee5fSAndroid Build Coastguard Worker 	page_offset = calc_page_offset(handle, record->offset);
2014*58e6ee5fSAndroid Build Coastguard Worker 	index = record->offset & (handle->page_size - 1);
2015*58e6ee5fSAndroid Build Coastguard Worker 
2016*58e6ee5fSAndroid Build Coastguard Worker 	ret = get_page(handle, record->cpu, page_offset);
2017*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
2018*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2019*58e6ee5fSAndroid Build Coastguard Worker 
2020*58e6ee5fSAndroid Build Coastguard Worker 	/* If the page is still mapped, there's nothing to do */
2021*58e6ee5fSAndroid Build Coastguard Worker 	if (ret)
2022*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
2023*58e6ee5fSAndroid Build Coastguard Worker 
2024*58e6ee5fSAndroid Build Coastguard Worker 	record->data = kbuffer_read_at_offset(cpu_data->kbuf, index, &record->ts);
2025*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->timestamp = record->ts;
2026*58e6ee5fSAndroid Build Coastguard Worker 
2027*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2028*58e6ee5fSAndroid Build Coastguard Worker }
2029*58e6ee5fSAndroid Build Coastguard Worker 
2030*58e6ee5fSAndroid Build Coastguard Worker /**
2031*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_read_cpu_first - get the first record in a CPU
2032*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
2033*58e6ee5fSAndroid Build Coastguard Worker  * @cpu: the CPU to search
2034*58e6ee5fSAndroid Build Coastguard Worker  *
2035*58e6ee5fSAndroid Build Coastguard Worker  * This returns the first (by time) record entry in a given CPU.
2036*58e6ee5fSAndroid Build Coastguard Worker  *
2037*58e6ee5fSAndroid Build Coastguard Worker  * The record returned must be freed.
2038*58e6ee5fSAndroid Build Coastguard Worker  */
2039*58e6ee5fSAndroid Build Coastguard Worker struct tep_record *
tracecmd_read_cpu_first(struct tracecmd_input * handle,int cpu)2040*58e6ee5fSAndroid Build Coastguard Worker tracecmd_read_cpu_first(struct tracecmd_input *handle, int cpu)
2041*58e6ee5fSAndroid Build Coastguard Worker {
2042*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long page_offset;
2043*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
2044*58e6ee5fSAndroid Build Coastguard Worker 
2045*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu >= handle->cpus)
2046*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
2047*58e6ee5fSAndroid Build Coastguard Worker 
2048*58e6ee5fSAndroid Build Coastguard Worker 	page_offset = calc_page_offset(handle, handle->cpu_data[cpu].file_offset);
2049*58e6ee5fSAndroid Build Coastguard Worker 
2050*58e6ee5fSAndroid Build Coastguard Worker 	ret = get_page(handle, cpu, page_offset);
2051*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
2052*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
2053*58e6ee5fSAndroid Build Coastguard Worker 
2054*58e6ee5fSAndroid Build Coastguard Worker 	/* If the page was already mapped, we need to reset it */
2055*58e6ee5fSAndroid Build Coastguard Worker 	if (ret)
2056*58e6ee5fSAndroid Build Coastguard Worker 		update_page_info(handle, cpu);
2057*58e6ee5fSAndroid Build Coastguard Worker 
2058*58e6ee5fSAndroid Build Coastguard Worker 	free_next(handle, cpu);
2059*58e6ee5fSAndroid Build Coastguard Worker 
2060*58e6ee5fSAndroid Build Coastguard Worker 	return tracecmd_read_data(handle, cpu);
2061*58e6ee5fSAndroid Build Coastguard Worker }
2062*58e6ee5fSAndroid Build Coastguard Worker 
2063*58e6ee5fSAndroid Build Coastguard Worker /**
2064*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_read_cpu_last - get the last record in a CPU
2065*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
2066*58e6ee5fSAndroid Build Coastguard Worker  * @cpu: the CPU to search
2067*58e6ee5fSAndroid Build Coastguard Worker  *
2068*58e6ee5fSAndroid Build Coastguard Worker  * This returns the last (by time) record entry in a given CPU.
2069*58e6ee5fSAndroid Build Coastguard Worker  *
2070*58e6ee5fSAndroid Build Coastguard Worker  * The record returned must be freed.
2071*58e6ee5fSAndroid Build Coastguard Worker  */
2072*58e6ee5fSAndroid Build Coastguard Worker struct tep_record *
tracecmd_read_cpu_last(struct tracecmd_input * handle,int cpu)2073*58e6ee5fSAndroid Build Coastguard Worker tracecmd_read_cpu_last(struct tracecmd_input *handle, int cpu)
2074*58e6ee5fSAndroid Build Coastguard Worker {
2075*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record = NULL;
2076*58e6ee5fSAndroid Build Coastguard Worker 	off64_t offset, page_offset;
2077*58e6ee5fSAndroid Build Coastguard Worker 
2078*58e6ee5fSAndroid Build Coastguard Worker 	offset = handle->cpu_data[cpu].file_offset +
2079*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data[cpu].file_size;
2080*58e6ee5fSAndroid Build Coastguard Worker 
2081*58e6ee5fSAndroid Build Coastguard Worker 	if (offset & (handle->page_size - 1))
2082*58e6ee5fSAndroid Build Coastguard Worker 		offset &= ~(handle->page_size - 1);
2083*58e6ee5fSAndroid Build Coastguard Worker 	else
2084*58e6ee5fSAndroid Build Coastguard Worker 		offset -= handle->page_size;
2085*58e6ee5fSAndroid Build Coastguard Worker 
2086*58e6ee5fSAndroid Build Coastguard Worker 	page_offset = offset;
2087*58e6ee5fSAndroid Build Coastguard Worker 
2088*58e6ee5fSAndroid Build Coastguard Worker  again:
2089*58e6ee5fSAndroid Build Coastguard Worker 	if (get_page(handle, cpu, page_offset) < 0)
2090*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
2091*58e6ee5fSAndroid Build Coastguard Worker 
2092*58e6ee5fSAndroid Build Coastguard Worker 	offset = page_offset;
2093*58e6ee5fSAndroid Build Coastguard Worker 
2094*58e6ee5fSAndroid Build Coastguard Worker 	do {
2095*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_free_record(record);
2096*58e6ee5fSAndroid Build Coastguard Worker 		record = tracecmd_read_data(handle, cpu);
2097*58e6ee5fSAndroid Build Coastguard Worker 		if (record)
2098*58e6ee5fSAndroid Build Coastguard Worker 			offset = record->offset;
2099*58e6ee5fSAndroid Build Coastguard Worker 	} while (record);
2100*58e6ee5fSAndroid Build Coastguard Worker 
2101*58e6ee5fSAndroid Build Coastguard Worker 	record = tracecmd_read_at(handle, offset, NULL);
2102*58e6ee5fSAndroid Build Coastguard Worker 
2103*58e6ee5fSAndroid Build Coastguard Worker 	/*
2104*58e6ee5fSAndroid Build Coastguard Worker 	 * It is possible that a page has just a timestamp
2105*58e6ee5fSAndroid Build Coastguard Worker 	 * or just padding on it.
2106*58e6ee5fSAndroid Build Coastguard Worker 	 */
2107*58e6ee5fSAndroid Build Coastguard Worker 	if (!record) {
2108*58e6ee5fSAndroid Build Coastguard Worker 		if (page_offset == handle->cpu_data[cpu].file_offset)
2109*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
2110*58e6ee5fSAndroid Build Coastguard Worker 		page_offset -= handle->page_size;
2111*58e6ee5fSAndroid Build Coastguard Worker 		goto again;
2112*58e6ee5fSAndroid Build Coastguard Worker 	}
2113*58e6ee5fSAndroid Build Coastguard Worker 
2114*58e6ee5fSAndroid Build Coastguard Worker 	return record;
2115*58e6ee5fSAndroid Build Coastguard Worker }
2116*58e6ee5fSAndroid Build Coastguard Worker 
2117*58e6ee5fSAndroid Build Coastguard Worker /**
2118*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_set_cpu_to_timestamp - set the CPU iterator to a given time
2119*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
2120*58e6ee5fSAndroid Build Coastguard Worker  * @cpu: the CPU pointer to set
2121*58e6ee5fSAndroid Build Coastguard Worker  * @ts: the timestamp to set the CPU at.
2122*58e6ee5fSAndroid Build Coastguard Worker  *
2123*58e6ee5fSAndroid Build Coastguard Worker  * This sets the CPU iterator used by tracecmd_read_data and
2124*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_peek_data to a location in the CPU storage near
2125*58e6ee5fSAndroid Build Coastguard Worker  * a given timestamp. It will try to set the iterator to a time before
2126*58e6ee5fSAndroid Build Coastguard Worker  * the time stamp and not actually at a given time.
2127*58e6ee5fSAndroid Build Coastguard Worker  *
2128*58e6ee5fSAndroid Build Coastguard Worker  * To use this to find a record in a time field, call this function
2129*58e6ee5fSAndroid Build Coastguard Worker  * first, than iterate with tracecmd_read_data to find the records
2130*58e6ee5fSAndroid Build Coastguard Worker  * you need.
2131*58e6ee5fSAndroid Build Coastguard Worker  */
2132*58e6ee5fSAndroid Build Coastguard Worker int
tracecmd_set_cpu_to_timestamp(struct tracecmd_input * handle,int cpu,unsigned long long ts)2133*58e6ee5fSAndroid Build Coastguard Worker tracecmd_set_cpu_to_timestamp(struct tracecmd_input *handle, int cpu,
2134*58e6ee5fSAndroid Build Coastguard Worker 			      unsigned long long ts)
2135*58e6ee5fSAndroid Build Coastguard Worker {
2136*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data = &handle->cpu_data[cpu];
2137*58e6ee5fSAndroid Build Coastguard Worker 	off64_t start, end, next;
2138*58e6ee5fSAndroid Build Coastguard Worker 
2139*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu < 0 || cpu >= handle->cpus) {
2140*58e6ee5fSAndroid Build Coastguard Worker 		errno = -EINVAL;
2141*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2142*58e6ee5fSAndroid Build Coastguard Worker 	}
2143*58e6ee5fSAndroid Build Coastguard Worker 
2144*58e6ee5fSAndroid Build Coastguard Worker 	if (!cpu_data->size)
2145*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2146*58e6ee5fSAndroid Build Coastguard Worker 
2147*58e6ee5fSAndroid Build Coastguard Worker 	if (!cpu_data->page) {
2148*58e6ee5fSAndroid Build Coastguard Worker 		if (init_cpu(handle, cpu))
2149*58e6ee5fSAndroid Build Coastguard Worker 		    return -1;
2150*58e6ee5fSAndroid Build Coastguard Worker 	}
2151*58e6ee5fSAndroid Build Coastguard Worker 
2152*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu_data->timestamp == ts) {
2153*58e6ee5fSAndroid Build Coastguard Worker 		/*
2154*58e6ee5fSAndroid Build Coastguard Worker 		 * If a record is cached, then that record is most
2155*58e6ee5fSAndroid Build Coastguard Worker 		 * likely the matching timestamp. Otherwise we need
2156*58e6ee5fSAndroid Build Coastguard Worker 		 * to start from the beginning of the index;
2157*58e6ee5fSAndroid Build Coastguard Worker 		 */
2158*58e6ee5fSAndroid Build Coastguard Worker 		if (!cpu_data->next ||
2159*58e6ee5fSAndroid Build Coastguard Worker 		    cpu_data->next->ts != ts)
2160*58e6ee5fSAndroid Build Coastguard Worker 			update_page_info(handle, cpu);
2161*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
2162*58e6ee5fSAndroid Build Coastguard Worker 	}
2163*58e6ee5fSAndroid Build Coastguard Worker 
2164*58e6ee5fSAndroid Build Coastguard Worker 	/* Set to the first record on current page */
2165*58e6ee5fSAndroid Build Coastguard Worker 	update_page_info(handle, cpu);
2166*58e6ee5fSAndroid Build Coastguard Worker 
2167*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu_data->timestamp < ts) {
2168*58e6ee5fSAndroid Build Coastguard Worker 		start = cpu_data->offset;
2169*58e6ee5fSAndroid Build Coastguard Worker 		end = cpu_data->file_offset + cpu_data->file_size;
2170*58e6ee5fSAndroid Build Coastguard Worker 		if (end & (handle->page_size - 1))
2171*58e6ee5fSAndroid Build Coastguard Worker 			end &= ~(handle->page_size - 1);
2172*58e6ee5fSAndroid Build Coastguard Worker 		else
2173*58e6ee5fSAndroid Build Coastguard Worker 			end -= handle->page_size;
2174*58e6ee5fSAndroid Build Coastguard Worker 		next = end;
2175*58e6ee5fSAndroid Build Coastguard Worker 	} else {
2176*58e6ee5fSAndroid Build Coastguard Worker 		end = cpu_data->offset;
2177*58e6ee5fSAndroid Build Coastguard Worker 		start = cpu_data->file_offset;
2178*58e6ee5fSAndroid Build Coastguard Worker 		next = start;
2179*58e6ee5fSAndroid Build Coastguard Worker 	}
2180*58e6ee5fSAndroid Build Coastguard Worker 
2181*58e6ee5fSAndroid Build Coastguard Worker 	while (start < end) {
2182*58e6ee5fSAndroid Build Coastguard Worker 		if (get_page(handle, cpu, next) < 0)
2183*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
2184*58e6ee5fSAndroid Build Coastguard Worker 
2185*58e6ee5fSAndroid Build Coastguard Worker 		if (cpu_data->timestamp == ts)
2186*58e6ee5fSAndroid Build Coastguard Worker 			break;
2187*58e6ee5fSAndroid Build Coastguard Worker 
2188*58e6ee5fSAndroid Build Coastguard Worker 		if (cpu_data->timestamp < ts)
2189*58e6ee5fSAndroid Build Coastguard Worker 			start = next;
2190*58e6ee5fSAndroid Build Coastguard Worker 		else
2191*58e6ee5fSAndroid Build Coastguard Worker 			end = next;
2192*58e6ee5fSAndroid Build Coastguard Worker 
2193*58e6ee5fSAndroid Build Coastguard Worker 		next = start + (end - start) / 2;
2194*58e6ee5fSAndroid Build Coastguard Worker 		next = calc_page_offset(handle, next);
2195*58e6ee5fSAndroid Build Coastguard Worker 
2196*58e6ee5fSAndroid Build Coastguard Worker 		/* Prevent an infinite loop if start and end are a page off */
2197*58e6ee5fSAndroid Build Coastguard Worker 		if (next == start)
2198*58e6ee5fSAndroid Build Coastguard Worker 			start = next += handle->page_size;
2199*58e6ee5fSAndroid Build Coastguard Worker 	}
2200*58e6ee5fSAndroid Build Coastguard Worker 
2201*58e6ee5fSAndroid Build Coastguard Worker 	/*
2202*58e6ee5fSAndroid Build Coastguard Worker 	 * We need to end up on a page before the time stamp.
2203*58e6ee5fSAndroid Build Coastguard Worker 	 * We go back even if the timestamp is the same. This is because
2204*58e6ee5fSAndroid Build Coastguard Worker 	 * we want the event with the timestamp, not the page. The page
2205*58e6ee5fSAndroid Build Coastguard Worker 	 * can start with the timestamp we are looking for, but the event
2206*58e6ee5fSAndroid Build Coastguard Worker 	 * may be on the previous page.
2207*58e6ee5fSAndroid Build Coastguard Worker 	 */
2208*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu_data->timestamp >= ts &&
2209*58e6ee5fSAndroid Build Coastguard Worker 	    cpu_data->offset > cpu_data->file_offset)
2210*58e6ee5fSAndroid Build Coastguard Worker 		get_page(handle, cpu, cpu_data->offset - handle->page_size);
2211*58e6ee5fSAndroid Build Coastguard Worker 
2212*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2213*58e6ee5fSAndroid Build Coastguard Worker }
2214*58e6ee5fSAndroid Build Coastguard Worker 
2215*58e6ee5fSAndroid Build Coastguard Worker /**
2216*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_set_all_cpus_to_timestamp - set all CPUs iterator to a given time
2217*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
2218*58e6ee5fSAndroid Build Coastguard Worker  * @cpu: the CPU pointer to set
2219*58e6ee5fSAndroid Build Coastguard Worker  * @ts: the timestamp to set the CPU at.
2220*58e6ee5fSAndroid Build Coastguard Worker  *
2221*58e6ee5fSAndroid Build Coastguard Worker  * This sets the CPU iterator used by tracecmd_read_data and
2222*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_peek_data to a location in the CPU storage near
2223*58e6ee5fSAndroid Build Coastguard Worker  * a given timestamp. It will try to set the iterator to a time before
2224*58e6ee5fSAndroid Build Coastguard Worker  * the time stamp and not actually at a given time.
2225*58e6ee5fSAndroid Build Coastguard Worker  *
2226*58e6ee5fSAndroid Build Coastguard Worker  * To use this to find a record in a time field, call this function
2227*58e6ee5fSAndroid Build Coastguard Worker  * first, than iterate with tracecmd_read_next_data to find the records
2228*58e6ee5fSAndroid Build Coastguard Worker  * you need.
2229*58e6ee5fSAndroid Build Coastguard Worker  */
2230*58e6ee5fSAndroid Build Coastguard Worker void
tracecmd_set_all_cpus_to_timestamp(struct tracecmd_input * handle,unsigned long long time)2231*58e6ee5fSAndroid Build Coastguard Worker tracecmd_set_all_cpus_to_timestamp(struct tracecmd_input *handle,
2232*58e6ee5fSAndroid Build Coastguard Worker 				   unsigned long long time)
2233*58e6ee5fSAndroid Build Coastguard Worker {
2234*58e6ee5fSAndroid Build Coastguard Worker 	int cpu;
2235*58e6ee5fSAndroid Build Coastguard Worker 
2236*58e6ee5fSAndroid Build Coastguard Worker 	for (cpu = 0; cpu < handle->cpus; cpu++)
2237*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_set_cpu_to_timestamp(handle, cpu, time);
2238*58e6ee5fSAndroid Build Coastguard Worker }
2239*58e6ee5fSAndroid Build Coastguard Worker 
2240*58e6ee5fSAndroid Build Coastguard Worker /**
2241*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_set_cursor - set the offset for the next tracecmd_read_data
2242*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
2243*58e6ee5fSAndroid Build Coastguard Worker  * @cpu: the CPU pointer to set
2244*58e6ee5fSAndroid Build Coastguard Worker  * @offset: the offset to place the cursor
2245*58e6ee5fSAndroid Build Coastguard Worker  *
2246*58e6ee5fSAndroid Build Coastguard Worker  * Set the pointer to the next read or peek. This is useful when
2247*58e6ee5fSAndroid Build Coastguard Worker  * needing to read sequentially and then look at another record
2248*58e6ee5fSAndroid Build Coastguard Worker  * out of sequence without breaking the iteration. This is done with:
2249*58e6ee5fSAndroid Build Coastguard Worker  *
2250*58e6ee5fSAndroid Build Coastguard Worker  *  record = tracecmd_peek_data()
2251*58e6ee5fSAndroid Build Coastguard Worker  *  offset = record->offset;
2252*58e6ee5fSAndroid Build Coastguard Worker  *  record = tracecmd_read_at();
2253*58e6ee5fSAndroid Build Coastguard Worker  *   - do what ever with record -
2254*58e6ee5fSAndroid Build Coastguard Worker  *  tracecmd_set_cursor(handle, cpu, offset);
2255*58e6ee5fSAndroid Build Coastguard Worker  *
2256*58e6ee5fSAndroid Build Coastguard Worker  *  Now the next tracecmd_peek_data or tracecmd_read_data will return
2257*58e6ee5fSAndroid Build Coastguard Worker  *  the original record.
2258*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_set_cursor(struct tracecmd_input * handle,int cpu,unsigned long long offset)2259*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_set_cursor(struct tracecmd_input *handle,
2260*58e6ee5fSAndroid Build Coastguard Worker 			int cpu, unsigned long long offset)
2261*58e6ee5fSAndroid Build Coastguard Worker {
2262*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data = &handle->cpu_data[cpu];
2263*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long page_offset;
2264*58e6ee5fSAndroid Build Coastguard Worker 
2265*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu < 0 || cpu >= handle->cpus)
2266*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2267*58e6ee5fSAndroid Build Coastguard Worker 
2268*58e6ee5fSAndroid Build Coastguard Worker 	if (offset < cpu_data->file_offset ||
2269*58e6ee5fSAndroid Build Coastguard Worker 	    offset > cpu_data->file_offset + cpu_data->file_size)
2270*58e6ee5fSAndroid Build Coastguard Worker 		return -1; 	/* cpu does not have this offset. */
2271*58e6ee5fSAndroid Build Coastguard Worker 
2272*58e6ee5fSAndroid Build Coastguard Worker 	/* Move this cpu index to point to this offest */
2273*58e6ee5fSAndroid Build Coastguard Worker 	page_offset = calc_page_offset(handle, offset);
2274*58e6ee5fSAndroid Build Coastguard Worker 
2275*58e6ee5fSAndroid Build Coastguard Worker 	if (get_page(handle, cpu, page_offset) < 0)
2276*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2277*58e6ee5fSAndroid Build Coastguard Worker 
2278*58e6ee5fSAndroid Build Coastguard Worker 	peek_event(handle, offset, cpu);
2279*58e6ee5fSAndroid Build Coastguard Worker 
2280*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2281*58e6ee5fSAndroid Build Coastguard Worker }
2282*58e6ee5fSAndroid Build Coastguard Worker 
2283*58e6ee5fSAndroid Build Coastguard Worker /**
2284*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_cursor - get the offset for the next tracecmd_read_data
2285*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
2286*58e6ee5fSAndroid Build Coastguard Worker  * @cpu: the CPU pointer to get the cursor from
2287*58e6ee5fSAndroid Build Coastguard Worker  *
2288*58e6ee5fSAndroid Build Coastguard Worker  * Returns the offset of the next record that would be read.
2289*58e6ee5fSAndroid Build Coastguard Worker  */
2290*58e6ee5fSAndroid Build Coastguard Worker unsigned long long
tracecmd_get_cursor(struct tracecmd_input * handle,int cpu)2291*58e6ee5fSAndroid Build Coastguard Worker tracecmd_get_cursor(struct tracecmd_input *handle, int cpu)
2292*58e6ee5fSAndroid Build Coastguard Worker {
2293*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data = &handle->cpu_data[cpu];
2294*58e6ee5fSAndroid Build Coastguard Worker 	struct kbuffer *kbuf = cpu_data->kbuf;
2295*58e6ee5fSAndroid Build Coastguard Worker 
2296*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu < 0 || cpu >= handle->cpus)
2297*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
2298*58e6ee5fSAndroid Build Coastguard Worker 
2299*58e6ee5fSAndroid Build Coastguard Worker 	/*
2300*58e6ee5fSAndroid Build Coastguard Worker 	 * Use the next pointer if it exists and matches the
2301*58e6ee5fSAndroid Build Coastguard Worker 	 * current timestamp.
2302*58e6ee5fSAndroid Build Coastguard Worker 	 */
2303*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu_data->next &&
2304*58e6ee5fSAndroid Build Coastguard Worker 	    cpu_data->next->ts == cpu_data->timestamp)
2305*58e6ee5fSAndroid Build Coastguard Worker 		return cpu_data->next->offset;
2306*58e6ee5fSAndroid Build Coastguard Worker 
2307*58e6ee5fSAndroid Build Coastguard Worker 	/*
2308*58e6ee5fSAndroid Build Coastguard Worker 	 * Either the next point does not exist, or it does
2309*58e6ee5fSAndroid Build Coastguard Worker 	 * not match the timestamp. The next read will use the
2310*58e6ee5fSAndroid Build Coastguard Worker 	 * current page.
2311*58e6ee5fSAndroid Build Coastguard Worker 	 *
2312*58e6ee5fSAndroid Build Coastguard Worker 	 * If the offset is at the end, then return that.
2313*58e6ee5fSAndroid Build Coastguard Worker 	 */
2314*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu_data->offset >= cpu_data->file_offset +
2315*58e6ee5fSAndroid Build Coastguard Worker 	    cpu_data->file_size)
2316*58e6ee5fSAndroid Build Coastguard Worker 		return cpu_data->offset;
2317*58e6ee5fSAndroid Build Coastguard Worker 
2318*58e6ee5fSAndroid Build Coastguard Worker 	return cpu_data->offset + kbuffer_curr_offset(kbuf);
2319*58e6ee5fSAndroid Build Coastguard Worker }
2320*58e6ee5fSAndroid Build Coastguard Worker 
2321*58e6ee5fSAndroid Build Coastguard Worker /**
2322*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_translate_data - create a record from raw data
2323*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
2324*58e6ee5fSAndroid Build Coastguard Worker  * @ptr: raw data to read
2325*58e6ee5fSAndroid Build Coastguard Worker  * @size: the size of the data
2326*58e6ee5fSAndroid Build Coastguard Worker  *
2327*58e6ee5fSAndroid Build Coastguard Worker  * This function tries to create a record from some given
2328*58e6ee5fSAndroid Build Coastguard Worker  * raw data. The data does not need to be from the trace.dat file.
2329*58e6ee5fSAndroid Build Coastguard Worker  * It can be stored from another location.
2330*58e6ee5fSAndroid Build Coastguard Worker  *
2331*58e6ee5fSAndroid Build Coastguard Worker  * Note, since the timestamp is calculated from within the trace
2332*58e6ee5fSAndroid Build Coastguard Worker  * buffer, the timestamp for the record will be zero, since it
2333*58e6ee5fSAndroid Build Coastguard Worker  * can't calculate it.
2334*58e6ee5fSAndroid Build Coastguard Worker  *
2335*58e6ee5fSAndroid Build Coastguard Worker  * The record returned must be freed.
2336*58e6ee5fSAndroid Build Coastguard Worker  */
2337*58e6ee5fSAndroid Build Coastguard Worker struct tep_record *
tracecmd_translate_data(struct tracecmd_input * handle,void * ptr,int size)2338*58e6ee5fSAndroid Build Coastguard Worker tracecmd_translate_data(struct tracecmd_input *handle,
2339*58e6ee5fSAndroid Build Coastguard Worker 			void *ptr, int size)
2340*58e6ee5fSAndroid Build Coastguard Worker {
2341*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = handle->pevent;
2342*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record;
2343*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int length;
2344*58e6ee5fSAndroid Build Coastguard Worker 	int swap = 1;
2345*58e6ee5fSAndroid Build Coastguard Worker 
2346*58e6ee5fSAndroid Build Coastguard Worker 	/* minimum record read is 8, (warn?) (TODO: make 8 into macro) */
2347*58e6ee5fSAndroid Build Coastguard Worker 	if (size < 8)
2348*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
2349*58e6ee5fSAndroid Build Coastguard Worker 
2350*58e6ee5fSAndroid Build Coastguard Worker 	record = malloc(sizeof(*record));
2351*58e6ee5fSAndroid Build Coastguard Worker 	if (!record)
2352*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
2353*58e6ee5fSAndroid Build Coastguard Worker 	memset(record, 0, sizeof(*record));
2354*58e6ee5fSAndroid Build Coastguard Worker 
2355*58e6ee5fSAndroid Build Coastguard Worker 	record->ref_count = 1;
2356*58e6ee5fSAndroid Build Coastguard Worker 	if (tep_is_local_bigendian(pevent) == tep_is_file_bigendian(pevent))
2357*58e6ee5fSAndroid Build Coastguard Worker 		swap = 0;
2358*58e6ee5fSAndroid Build Coastguard Worker 	record->data = kbuffer_translate_data(swap, ptr, &length);
2359*58e6ee5fSAndroid Build Coastguard Worker 	record->size = length;
2360*58e6ee5fSAndroid Build Coastguard Worker 	if (record->data)
2361*58e6ee5fSAndroid Build Coastguard Worker 		record->record_size = record->size + (record->data - ptr);
2362*58e6ee5fSAndroid Build Coastguard Worker 
2363*58e6ee5fSAndroid Build Coastguard Worker 	return record;
2364*58e6ee5fSAndroid Build Coastguard Worker }
2365*58e6ee5fSAndroid Build Coastguard Worker 
2366*58e6ee5fSAndroid Build Coastguard Worker 
2367*58e6ee5fSAndroid Build Coastguard Worker /**
2368*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_peek_data - return the record at the current location.
2369*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
2370*58e6ee5fSAndroid Build Coastguard Worker  * @cpu: the CPU to pull from
2371*58e6ee5fSAndroid Build Coastguard Worker  *
2372*58e6ee5fSAndroid Build Coastguard Worker  * This returns the record at the current location of the CPU
2373*58e6ee5fSAndroid Build Coastguard Worker  * iterator. It does not increment the CPU iterator.
2374*58e6ee5fSAndroid Build Coastguard Worker  */
2375*58e6ee5fSAndroid Build Coastguard Worker struct tep_record *
tracecmd_peek_data(struct tracecmd_input * handle,int cpu)2376*58e6ee5fSAndroid Build Coastguard Worker tracecmd_peek_data(struct tracecmd_input *handle, int cpu)
2377*58e6ee5fSAndroid Build Coastguard Worker {
2378*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record;
2379*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long ts;
2380*58e6ee5fSAndroid Build Coastguard Worker 	struct kbuffer *kbuf;
2381*58e6ee5fSAndroid Build Coastguard Worker 	struct page *page;
2382*58e6ee5fSAndroid Build Coastguard Worker 	int index;
2383*58e6ee5fSAndroid Build Coastguard Worker 	void *data;
2384*58e6ee5fSAndroid Build Coastguard Worker 
2385*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu >= handle->cpus)
2386*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
2387*58e6ee5fSAndroid Build Coastguard Worker 
2388*58e6ee5fSAndroid Build Coastguard Worker 	page = handle->cpu_data[cpu].page;
2389*58e6ee5fSAndroid Build Coastguard Worker 	kbuf = handle->cpu_data[cpu].kbuf;
2390*58e6ee5fSAndroid Build Coastguard Worker 
2391*58e6ee5fSAndroid Build Coastguard Worker 	/* Hack to work around function graph read ahead */
2392*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_curr_thread_handle = handle;
2393*58e6ee5fSAndroid Build Coastguard Worker 
2394*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->cpu_data[cpu].next) {
2395*58e6ee5fSAndroid Build Coastguard Worker 
2396*58e6ee5fSAndroid Build Coastguard Worker 		record = handle->cpu_data[cpu].next;
2397*58e6ee5fSAndroid Build Coastguard Worker 		if (!record->data) {
2398*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_critical("Something freed the record");
2399*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
2400*58e6ee5fSAndroid Build Coastguard Worker 		}
2401*58e6ee5fSAndroid Build Coastguard Worker 
2402*58e6ee5fSAndroid Build Coastguard Worker 		if (handle->cpu_data[cpu].timestamp == record->ts)
2403*58e6ee5fSAndroid Build Coastguard Worker 			return record;
2404*58e6ee5fSAndroid Build Coastguard Worker 
2405*58e6ee5fSAndroid Build Coastguard Worker 		/*
2406*58e6ee5fSAndroid Build Coastguard Worker 		 * The timestamp changed, which means the cached
2407*58e6ee5fSAndroid Build Coastguard Worker 		 * record is no longer valid. Reread a new record.
2408*58e6ee5fSAndroid Build Coastguard Worker 		 */
2409*58e6ee5fSAndroid Build Coastguard Worker 		free_next(handle, cpu);
2410*58e6ee5fSAndroid Build Coastguard Worker 	}
2411*58e6ee5fSAndroid Build Coastguard Worker 
2412*58e6ee5fSAndroid Build Coastguard Worker read_again:
2413*58e6ee5fSAndroid Build Coastguard Worker 	if (!page) {
2414*58e6ee5fSAndroid Build Coastguard Worker 		if (handle->use_pipe) {
2415*58e6ee5fSAndroid Build Coastguard Worker 			get_next_page(handle, cpu);
2416*58e6ee5fSAndroid Build Coastguard Worker 			page = handle->cpu_data[cpu].page;
2417*58e6ee5fSAndroid Build Coastguard Worker 		}
2418*58e6ee5fSAndroid Build Coastguard Worker 		if (!page)
2419*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
2420*58e6ee5fSAndroid Build Coastguard Worker 	}
2421*58e6ee5fSAndroid Build Coastguard Worker 
2422*58e6ee5fSAndroid Build Coastguard Worker 	data = kbuffer_read_event(kbuf, &ts);
2423*58e6ee5fSAndroid Build Coastguard Worker 	if (!data) {
2424*58e6ee5fSAndroid Build Coastguard Worker 		if (get_next_page(handle, cpu))
2425*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
2426*58e6ee5fSAndroid Build Coastguard Worker 		page = handle->cpu_data[cpu].page;
2427*58e6ee5fSAndroid Build Coastguard Worker 		goto read_again;
2428*58e6ee5fSAndroid Build Coastguard Worker 	}
2429*58e6ee5fSAndroid Build Coastguard Worker 
2430*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].timestamp = timestamp_calc(ts, cpu, handle);
2431*58e6ee5fSAndroid Build Coastguard Worker 
2432*58e6ee5fSAndroid Build Coastguard Worker 	index = kbuffer_curr_offset(kbuf);
2433*58e6ee5fSAndroid Build Coastguard Worker 
2434*58e6ee5fSAndroid Build Coastguard Worker 	record = malloc(sizeof(*record));
2435*58e6ee5fSAndroid Build Coastguard Worker 	if (!record)
2436*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
2437*58e6ee5fSAndroid Build Coastguard Worker 	memset(record, 0, sizeof(*record));
2438*58e6ee5fSAndroid Build Coastguard Worker 
2439*58e6ee5fSAndroid Build Coastguard Worker 	record->ts = handle->cpu_data[cpu].timestamp;
2440*58e6ee5fSAndroid Build Coastguard Worker 	record->size = kbuffer_event_size(kbuf);
2441*58e6ee5fSAndroid Build Coastguard Worker 	record->cpu = handle->cpu_data[cpu].cpu;
2442*58e6ee5fSAndroid Build Coastguard Worker 	record->data = data;
2443*58e6ee5fSAndroid Build Coastguard Worker 	record->offset = handle->cpu_data[cpu].offset + index;
2444*58e6ee5fSAndroid Build Coastguard Worker 	record->missed_events = kbuffer_missed_events(kbuf);
2445*58e6ee5fSAndroid Build Coastguard Worker 	record->ref_count = 1;
2446*58e6ee5fSAndroid Build Coastguard Worker 	record->locked = 1;
2447*58e6ee5fSAndroid Build Coastguard Worker 
2448*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].next = record;
2449*58e6ee5fSAndroid Build Coastguard Worker 
2450*58e6ee5fSAndroid Build Coastguard Worker 	record->record_size = kbuffer_curr_size(kbuf);
2451*58e6ee5fSAndroid Build Coastguard Worker 	record->priv = page;
2452*58e6ee5fSAndroid Build Coastguard Worker 	add_record(page, record);
2453*58e6ee5fSAndroid Build Coastguard Worker 	page->ref_count++;
2454*58e6ee5fSAndroid Build Coastguard Worker 
2455*58e6ee5fSAndroid Build Coastguard Worker 	kbuffer_next_event(kbuf, NULL);
2456*58e6ee5fSAndroid Build Coastguard Worker 
2457*58e6ee5fSAndroid Build Coastguard Worker 	return record;
2458*58e6ee5fSAndroid Build Coastguard Worker }
2459*58e6ee5fSAndroid Build Coastguard Worker 
2460*58e6ee5fSAndroid Build Coastguard Worker /**
2461*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_read_data - read the next record and increment
2462*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
2463*58e6ee5fSAndroid Build Coastguard Worker  * @cpu: the CPU to pull from
2464*58e6ee5fSAndroid Build Coastguard Worker  *
2465*58e6ee5fSAndroid Build Coastguard Worker  * This returns the record at the current location of the CPU
2466*58e6ee5fSAndroid Build Coastguard Worker  * iterator and increments the CPU iterator.
2467*58e6ee5fSAndroid Build Coastguard Worker  *
2468*58e6ee5fSAndroid Build Coastguard Worker  * The record returned must be freed.
2469*58e6ee5fSAndroid Build Coastguard Worker  */
2470*58e6ee5fSAndroid Build Coastguard Worker struct tep_record *
tracecmd_read_data(struct tracecmd_input * handle,int cpu)2471*58e6ee5fSAndroid Build Coastguard Worker tracecmd_read_data(struct tracecmd_input *handle, int cpu)
2472*58e6ee5fSAndroid Build Coastguard Worker {
2473*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record;
2474*58e6ee5fSAndroid Build Coastguard Worker 
2475*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu >= handle->cpus)
2476*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
2477*58e6ee5fSAndroid Build Coastguard Worker 
2478*58e6ee5fSAndroid Build Coastguard Worker 	record = tracecmd_peek_data(handle, cpu);
2479*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].next = NULL;
2480*58e6ee5fSAndroid Build Coastguard Worker 	if (record) {
2481*58e6ee5fSAndroid Build Coastguard Worker 		record->locked = 0;
2482*58e6ee5fSAndroid Build Coastguard Worker #if DEBUG_RECORD
2483*58e6ee5fSAndroid Build Coastguard Worker 		record->alloc_addr = (unsigned long)__builtin_return_address(0);
2484*58e6ee5fSAndroid Build Coastguard Worker #endif
2485*58e6ee5fSAndroid Build Coastguard Worker 	}
2486*58e6ee5fSAndroid Build Coastguard Worker 	return record;
2487*58e6ee5fSAndroid Build Coastguard Worker }
2488*58e6ee5fSAndroid Build Coastguard Worker 
2489*58e6ee5fSAndroid Build Coastguard Worker /**
2490*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_read_next_data - read the next record
2491*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle to the trace.dat file
2492*58e6ee5fSAndroid Build Coastguard Worker  * @rec_cpu: return pointer to the CPU that the record belongs to
2493*58e6ee5fSAndroid Build Coastguard Worker  *
2494*58e6ee5fSAndroid Build Coastguard Worker  * This returns the next record by time. This is different than
2495*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_read_data in that it looks at all CPUs. It does a peek
2496*58e6ee5fSAndroid Build Coastguard Worker  * at each CPU and the record with the earliest time stame is
2497*58e6ee5fSAndroid Build Coastguard Worker  * returned. If @rec_cpu is not NULL it gets the CPU id the record was
2498*58e6ee5fSAndroid Build Coastguard Worker  * on. The CPU cursor of the returned record is moved to the
2499*58e6ee5fSAndroid Build Coastguard Worker  * next record.
2500*58e6ee5fSAndroid Build Coastguard Worker  *
2501*58e6ee5fSAndroid Build Coastguard Worker  * Multiple reads of this function will return a serialized list
2502*58e6ee5fSAndroid Build Coastguard Worker  * of all records for all CPUs in order of time stamp.
2503*58e6ee5fSAndroid Build Coastguard Worker  *
2504*58e6ee5fSAndroid Build Coastguard Worker  * The record returned must be freed.
2505*58e6ee5fSAndroid Build Coastguard Worker  */
2506*58e6ee5fSAndroid Build Coastguard Worker struct tep_record *
tracecmd_read_next_data(struct tracecmd_input * handle,int * rec_cpu)2507*58e6ee5fSAndroid Build Coastguard Worker tracecmd_read_next_data(struct tracecmd_input *handle, int *rec_cpu)
2508*58e6ee5fSAndroid Build Coastguard Worker {
2509*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record;
2510*58e6ee5fSAndroid Build Coastguard Worker 	int next_cpu;
2511*58e6ee5fSAndroid Build Coastguard Worker 
2512*58e6ee5fSAndroid Build Coastguard Worker 	record = tracecmd_peek_next_data(handle, &next_cpu);
2513*58e6ee5fSAndroid Build Coastguard Worker 	if (!record)
2514*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
2515*58e6ee5fSAndroid Build Coastguard Worker 
2516*58e6ee5fSAndroid Build Coastguard Worker 	if (rec_cpu)
2517*58e6ee5fSAndroid Build Coastguard Worker 		*rec_cpu = next_cpu;
2518*58e6ee5fSAndroid Build Coastguard Worker 
2519*58e6ee5fSAndroid Build Coastguard Worker 	return tracecmd_read_data(handle, next_cpu);
2520*58e6ee5fSAndroid Build Coastguard Worker }
2521*58e6ee5fSAndroid Build Coastguard Worker 
2522*58e6ee5fSAndroid Build Coastguard Worker /**
2523*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_peek_next_data - return the next record
2524*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle to the trace.dat file
2525*58e6ee5fSAndroid Build Coastguard Worker  * @rec_cpu: return pointer to the CPU that the record belongs to
2526*58e6ee5fSAndroid Build Coastguard Worker  *
2527*58e6ee5fSAndroid Build Coastguard Worker  * This returns the next record by time. This is different than
2528*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_peek_data in that it looks at all CPUs. It does a peek
2529*58e6ee5fSAndroid Build Coastguard Worker  * at each CPU and the record with the earliest time stame is
2530*58e6ee5fSAndroid Build Coastguard Worker  * returned. If @rec_cpu is not NULL it gets the CPU id the record was
2531*58e6ee5fSAndroid Build Coastguard Worker  * on. It does not increment the CPU iterator.
2532*58e6ee5fSAndroid Build Coastguard Worker  */
2533*58e6ee5fSAndroid Build Coastguard Worker struct tep_record *
tracecmd_peek_next_data(struct tracecmd_input * handle,int * rec_cpu)2534*58e6ee5fSAndroid Build Coastguard Worker tracecmd_peek_next_data(struct tracecmd_input *handle, int *rec_cpu)
2535*58e6ee5fSAndroid Build Coastguard Worker {
2536*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long ts;
2537*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *record, *next_record = NULL;
2538*58e6ee5fSAndroid Build Coastguard Worker 	int next_cpu;
2539*58e6ee5fSAndroid Build Coastguard Worker 	int cpu;
2540*58e6ee5fSAndroid Build Coastguard Worker 
2541*58e6ee5fSAndroid Build Coastguard Worker 	if (rec_cpu)
2542*58e6ee5fSAndroid Build Coastguard Worker 		*rec_cpu = -1;
2543*58e6ee5fSAndroid Build Coastguard Worker 
2544*58e6ee5fSAndroid Build Coastguard Worker 	next_cpu = -1;
2545*58e6ee5fSAndroid Build Coastguard Worker 	ts = 0;
2546*58e6ee5fSAndroid Build Coastguard Worker 
2547*58e6ee5fSAndroid Build Coastguard Worker 	for (cpu = 0; cpu < handle->cpus; cpu++) {
2548*58e6ee5fSAndroid Build Coastguard Worker 		record = tracecmd_peek_data(handle, cpu);
2549*58e6ee5fSAndroid Build Coastguard Worker 		if (record && (!next_record || record->ts < ts)) {
2550*58e6ee5fSAndroid Build Coastguard Worker 			ts = record->ts;
2551*58e6ee5fSAndroid Build Coastguard Worker 			next_cpu = cpu;
2552*58e6ee5fSAndroid Build Coastguard Worker 			next_record = record;
2553*58e6ee5fSAndroid Build Coastguard Worker 		}
2554*58e6ee5fSAndroid Build Coastguard Worker 	}
2555*58e6ee5fSAndroid Build Coastguard Worker 
2556*58e6ee5fSAndroid Build Coastguard Worker 	if (next_record) {
2557*58e6ee5fSAndroid Build Coastguard Worker 		if (rec_cpu)
2558*58e6ee5fSAndroid Build Coastguard Worker 			*rec_cpu = next_cpu;
2559*58e6ee5fSAndroid Build Coastguard Worker 		return next_record;
2560*58e6ee5fSAndroid Build Coastguard Worker 	}
2561*58e6ee5fSAndroid Build Coastguard Worker 
2562*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
2563*58e6ee5fSAndroid Build Coastguard Worker }
2564*58e6ee5fSAndroid Build Coastguard Worker 
2565*58e6ee5fSAndroid Build Coastguard Worker /**
2566*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_read_prev - read the record before the given record
2567*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle to the trace.dat file
2568*58e6ee5fSAndroid Build Coastguard Worker  * @record: the record to use to find the previous record.
2569*58e6ee5fSAndroid Build Coastguard Worker  *
2570*58e6ee5fSAndroid Build Coastguard Worker  * This returns the record before the @record on its CPU. If
2571*58e6ee5fSAndroid Build Coastguard Worker  * @record is the first record, NULL is returned. The cursor is set
2572*58e6ee5fSAndroid Build Coastguard Worker  * as if the previous record was read by tracecmd_read_data().
2573*58e6ee5fSAndroid Build Coastguard Worker  *
2574*58e6ee5fSAndroid Build Coastguard Worker  * @record can not be NULL, otherwise NULL is returned; the
2575*58e6ee5fSAndroid Build Coastguard Worker  * record ownership goes to this function.
2576*58e6ee5fSAndroid Build Coastguard Worker  *
2577*58e6ee5fSAndroid Build Coastguard Worker  * Note, this is not that fast of an algorithm, since it needs
2578*58e6ee5fSAndroid Build Coastguard Worker  * to build the timestamp for the record.
2579*58e6ee5fSAndroid Build Coastguard Worker  *
2580*58e6ee5fSAndroid Build Coastguard Worker  * The record returned must be freed with tracecmd_free_record().
2581*58e6ee5fSAndroid Build Coastguard Worker  */
2582*58e6ee5fSAndroid Build Coastguard Worker struct tep_record *
tracecmd_read_prev(struct tracecmd_input * handle,struct tep_record * record)2583*58e6ee5fSAndroid Build Coastguard Worker tracecmd_read_prev(struct tracecmd_input *handle, struct tep_record *record)
2584*58e6ee5fSAndroid Build Coastguard Worker {
2585*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset, page_offset;;
2586*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data;
2587*58e6ee5fSAndroid Build Coastguard Worker 	int index;
2588*58e6ee5fSAndroid Build Coastguard Worker 	int cpu;
2589*58e6ee5fSAndroid Build Coastguard Worker 
2590*58e6ee5fSAndroid Build Coastguard Worker 	if (!record)
2591*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
2592*58e6ee5fSAndroid Build Coastguard Worker 
2593*58e6ee5fSAndroid Build Coastguard Worker 	cpu = record->cpu;
2594*58e6ee5fSAndroid Build Coastguard Worker 	offset = record->offset;
2595*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data = &handle->cpu_data[cpu];
2596*58e6ee5fSAndroid Build Coastguard Worker 
2597*58e6ee5fSAndroid Build Coastguard Worker 	page_offset = calc_page_offset(handle, offset);
2598*58e6ee5fSAndroid Build Coastguard Worker 	index = offset - page_offset;
2599*58e6ee5fSAndroid Build Coastguard Worker 
2600*58e6ee5fSAndroid Build Coastguard Worker 	/* Note, the record passed in could have been a peek */
2601*58e6ee5fSAndroid Build Coastguard Worker 	free_next(handle, cpu);
2602*58e6ee5fSAndroid Build Coastguard Worker 
2603*58e6ee5fSAndroid Build Coastguard Worker 	/* Reset the cursor */
2604*58e6ee5fSAndroid Build Coastguard Worker 	/* Should not happen */
2605*58e6ee5fSAndroid Build Coastguard Worker 	if (get_page(handle, cpu, page_offset) < 0)
2606*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
2607*58e6ee5fSAndroid Build Coastguard Worker 
2608*58e6ee5fSAndroid Build Coastguard Worker 	update_page_info(handle, cpu);
2609*58e6ee5fSAndroid Build Coastguard Worker 
2610*58e6ee5fSAndroid Build Coastguard Worker 	/* Find the record before this record */
2611*58e6ee5fSAndroid Build Coastguard Worker 	index = 0;
2612*58e6ee5fSAndroid Build Coastguard Worker 	for (;;) {
2613*58e6ee5fSAndroid Build Coastguard Worker 		record = tracecmd_read_data(handle, cpu);
2614*58e6ee5fSAndroid Build Coastguard Worker 		/* Should not happen! */
2615*58e6ee5fSAndroid Build Coastguard Worker 		if (!record)
2616*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
2617*58e6ee5fSAndroid Build Coastguard Worker 		if (record->offset == offset)
2618*58e6ee5fSAndroid Build Coastguard Worker 			break;
2619*58e6ee5fSAndroid Build Coastguard Worker 		index = record->offset - page_offset;
2620*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_free_record(record);
2621*58e6ee5fSAndroid Build Coastguard Worker 	}
2622*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_free_record(record);
2623*58e6ee5fSAndroid Build Coastguard Worker 
2624*58e6ee5fSAndroid Build Coastguard Worker 	if (index)
2625*58e6ee5fSAndroid Build Coastguard Worker 		/* we found our record */
2626*58e6ee5fSAndroid Build Coastguard Worker 		return tracecmd_read_at(handle, page_offset + index, NULL);
2627*58e6ee5fSAndroid Build Coastguard Worker 
2628*58e6ee5fSAndroid Build Coastguard Worker 	/* reset the index to start at the beginning of the page */
2629*58e6ee5fSAndroid Build Coastguard Worker 	update_page_info(handle, cpu);
2630*58e6ee5fSAndroid Build Coastguard Worker 
2631*58e6ee5fSAndroid Build Coastguard Worker 	/* The previous record is on the previous page */
2632*58e6ee5fSAndroid Build Coastguard Worker 	for (;;) {
2633*58e6ee5fSAndroid Build Coastguard Worker 		/* check if this is the first page */
2634*58e6ee5fSAndroid Build Coastguard Worker 		if (page_offset == cpu_data->file_offset)
2635*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
2636*58e6ee5fSAndroid Build Coastguard Worker 		page_offset -= handle->page_size;
2637*58e6ee5fSAndroid Build Coastguard Worker 
2638*58e6ee5fSAndroid Build Coastguard Worker 		/* Updating page to a new page will reset index to 0 */
2639*58e6ee5fSAndroid Build Coastguard Worker 		get_page(handle, cpu, page_offset);
2640*58e6ee5fSAndroid Build Coastguard Worker 
2641*58e6ee5fSAndroid Build Coastguard Worker 		record = NULL;
2642*58e6ee5fSAndroid Build Coastguard Worker 		index = 0;
2643*58e6ee5fSAndroid Build Coastguard Worker 		do {
2644*58e6ee5fSAndroid Build Coastguard Worker 			if (record) {
2645*58e6ee5fSAndroid Build Coastguard Worker 				index = record->offset - page_offset;
2646*58e6ee5fSAndroid Build Coastguard Worker 				tracecmd_free_record(record);
2647*58e6ee5fSAndroid Build Coastguard Worker 			}
2648*58e6ee5fSAndroid Build Coastguard Worker 			record = tracecmd_read_data(handle, cpu);
2649*58e6ee5fSAndroid Build Coastguard Worker 			/* Should not happen */
2650*58e6ee5fSAndroid Build Coastguard Worker 			if (!record)
2651*58e6ee5fSAndroid Build Coastguard Worker 				return NULL;
2652*58e6ee5fSAndroid Build Coastguard Worker 		} while (record->offset != offset);
2653*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_free_record(record);
2654*58e6ee5fSAndroid Build Coastguard Worker 
2655*58e6ee5fSAndroid Build Coastguard Worker 		if (index)
2656*58e6ee5fSAndroid Build Coastguard Worker 			/* we found our record */
2657*58e6ee5fSAndroid Build Coastguard Worker 			return tracecmd_read_at(handle, page_offset + index, NULL);
2658*58e6ee5fSAndroid Build Coastguard Worker 	}
2659*58e6ee5fSAndroid Build Coastguard Worker 
2660*58e6ee5fSAndroid Build Coastguard Worker 	/* Not reached */
2661*58e6ee5fSAndroid Build Coastguard Worker }
2662*58e6ee5fSAndroid Build Coastguard Worker 
init_cpu_zfile(struct tracecmd_input * handle,int cpu)2663*58e6ee5fSAndroid Build Coastguard Worker static int init_cpu_zfile(struct tracecmd_input *handle, int cpu)
2664*58e6ee5fSAndroid Build Coastguard Worker {
2665*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data;
2666*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
2667*58e6ee5fSAndroid Build Coastguard Worker 	off64_t offset;
2668*58e6ee5fSAndroid Build Coastguard Worker 
2669*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data = &handle->cpu_data[cpu];
2670*58e6ee5fSAndroid Build Coastguard Worker 	offset = lseek64(handle->fd, 0, SEEK_CUR);
2671*58e6ee5fSAndroid Build Coastguard Worker 	if (lseek64(handle->fd, cpu_data->file_offset, SEEK_SET) == (off_t)-1)
2672*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2673*58e6ee5fSAndroid Build Coastguard Worker 
2674*58e6ee5fSAndroid Build Coastguard Worker 	strcpy(cpu_data->compress.file, COMPR_TEMP_FILE);
2675*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->compress.fd = mkstemp(cpu_data->compress.file);
2676*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu_data->compress.fd < 0)
2677*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2678*58e6ee5fSAndroid Build Coastguard Worker 
2679*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_uncompress_copy_to(handle->compress, cpu_data->compress.fd, NULL, &size))
2680*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2681*58e6ee5fSAndroid Build Coastguard Worker 
2682*58e6ee5fSAndroid Build Coastguard Worker 	if (lseek64(handle->fd, offset, SEEK_SET) == (off_t)-1)
2683*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2684*58e6ee5fSAndroid Build Coastguard Worker 
2685*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->file_offset = handle->next_offset;
2686*58e6ee5fSAndroid Build Coastguard Worker 	handle->next_offset = (handle->next_offset + size + handle->page_size - 1) &
2687*58e6ee5fSAndroid Build Coastguard Worker 		~(handle->page_size - 1);
2688*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->offset = cpu_data->file_offset;
2689*58e6ee5fSAndroid Build Coastguard Worker 
2690*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->file_size = size;
2691*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->size = size;
2692*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2693*58e6ee5fSAndroid Build Coastguard Worker }
2694*58e6ee5fSAndroid Build Coastguard Worker 
init_cpu_zpage(struct tracecmd_input * handle,int cpu)2695*58e6ee5fSAndroid Build Coastguard Worker static int init_cpu_zpage(struct tracecmd_input *handle, int cpu)
2696*58e6ee5fSAndroid Build Coastguard Worker {
2697*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data = &handle->cpu_data[cpu];
2698*58e6ee5fSAndroid Build Coastguard Worker 	int count;
2699*58e6ee5fSAndroid Build Coastguard Worker 	int i;
2700*58e6ee5fSAndroid Build Coastguard Worker 
2701*58e6ee5fSAndroid Build Coastguard Worker 	if (lseek64(handle->fd, cpu_data->file_offset, SEEK_SET) == (off_t)-1)
2702*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2703*58e6ee5fSAndroid Build Coastguard Worker 
2704*58e6ee5fSAndroid Build Coastguard Worker 	count = tracecmd_load_chunks_info(handle->compress, &cpu_data->compress.chunks);
2705*58e6ee5fSAndroid Build Coastguard Worker 	if (count < 0)
2706*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2707*58e6ee5fSAndroid Build Coastguard Worker 
2708*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->compress.count = count;
2709*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->compress.last_chunk = 0;
2710*58e6ee5fSAndroid Build Coastguard Worker 
2711*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->file_offset = handle->next_offset;
2712*58e6ee5fSAndroid Build Coastguard Worker 
2713*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < count; i++)
2714*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->file_size += cpu_data->compress.chunks[i].size;
2715*58e6ee5fSAndroid Build Coastguard Worker 
2716*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->offset = cpu_data->file_offset;
2717*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->size = cpu_data->file_size;
2718*58e6ee5fSAndroid Build Coastguard Worker 	handle->next_offset = (handle->next_offset + cpu_data->size + handle->page_size - 1) &
2719*58e6ee5fSAndroid Build Coastguard Worker 		~(handle->page_size - 1);
2720*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2721*58e6ee5fSAndroid Build Coastguard Worker }
2722*58e6ee5fSAndroid Build Coastguard Worker 
init_cpu(struct tracecmd_input * handle,int cpu)2723*58e6ee5fSAndroid Build Coastguard Worker static int init_cpu(struct tracecmd_input *handle, int cpu)
2724*58e6ee5fSAndroid Build Coastguard Worker {
2725*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data = &handle->cpu_data[cpu];
2726*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
2727*58e6ee5fSAndroid Build Coastguard Worker 	int i;
2728*58e6ee5fSAndroid Build Coastguard Worker 
2729*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->cpu_compressed && cpu_data->file_size > 0) {
2730*58e6ee5fSAndroid Build Coastguard Worker 		if (handle->read_zpage)
2731*58e6ee5fSAndroid Build Coastguard Worker 			ret = init_cpu_zpage(handle, cpu);
2732*58e6ee5fSAndroid Build Coastguard Worker 		else
2733*58e6ee5fSAndroid Build Coastguard Worker 			ret = init_cpu_zfile(handle, cpu);
2734*58e6ee5fSAndroid Build Coastguard Worker 		if (ret)
2735*58e6ee5fSAndroid Build Coastguard Worker 			return ret;
2736*58e6ee5fSAndroid Build Coastguard Worker 	} else {
2737*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->offset = cpu_data->file_offset;
2738*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->size = cpu_data->file_size;
2739*58e6ee5fSAndroid Build Coastguard Worker 	}
2740*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->timestamp = 0;
2741*58e6ee5fSAndroid Build Coastguard Worker 
2742*58e6ee5fSAndroid Build Coastguard Worker 	list_head_init(&cpu_data->page_maps);
2743*58e6ee5fSAndroid Build Coastguard Worker 	list_head_init(&cpu_data->compress.cache);
2744*58e6ee5fSAndroid Build Coastguard Worker 
2745*58e6ee5fSAndroid Build Coastguard Worker 	if (!cpu_data->size) {
2746*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_info("CPU %d is empty", cpu);
2747*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
2748*58e6ee5fSAndroid Build Coastguard Worker 	}
2749*58e6ee5fSAndroid Build Coastguard Worker 
2750*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->nr_pages = (cpu_data->size + handle->page_size - 1) / handle->page_size;
2751*58e6ee5fSAndroid Build Coastguard Worker 	if (!cpu_data->nr_pages)
2752*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->nr_pages = 1;
2753*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->pages = calloc(cpu_data->nr_pages, sizeof(*cpu_data->pages));
2754*58e6ee5fSAndroid Build Coastguard Worker 	if (!cpu_data->pages)
2755*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2756*58e6ee5fSAndroid Build Coastguard Worker 
2757*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->use_pipe) {
2758*58e6ee5fSAndroid Build Coastguard Worker 		/* Just make a page, it will be nuked later */
2759*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->page = malloc(sizeof(*cpu_data->page));
2760*58e6ee5fSAndroid Build Coastguard Worker 		if (!cpu_data->page)
2761*58e6ee5fSAndroid Build Coastguard Worker 			goto fail;
2762*58e6ee5fSAndroid Build Coastguard Worker 
2763*58e6ee5fSAndroid Build Coastguard Worker 		memset(cpu_data->page, 0, sizeof(*cpu_data->page));
2764*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->pages[0] = cpu_data->page;
2765*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->page_cnt = 1;
2766*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->page->ref_count = 1;
2767*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
2768*58e6ee5fSAndroid Build Coastguard Worker 	}
2769*58e6ee5fSAndroid Build Coastguard Worker 
2770*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->page = allocate_page(handle, cpu, cpu_data->offset);
2771*58e6ee5fSAndroid Build Coastguard Worker 	if (!cpu_data->page && !handle->read_page) {
2772*58e6ee5fSAndroid Build Coastguard Worker 		perror("mmap");
2773*58e6ee5fSAndroid Build Coastguard Worker 		fprintf(stderr, "Can not mmap file, will read instead\n");
2774*58e6ee5fSAndroid Build Coastguard Worker 
2775*58e6ee5fSAndroid Build Coastguard Worker 		if (cpu) {
2776*58e6ee5fSAndroid Build Coastguard Worker 			/*
2777*58e6ee5fSAndroid Build Coastguard Worker 			 * If the other CPUs had size and was able to mmap
2778*58e6ee5fSAndroid Build Coastguard Worker 			 * then bail.
2779*58e6ee5fSAndroid Build Coastguard Worker 			 */
2780*58e6ee5fSAndroid Build Coastguard Worker 			for (i = 0; i < cpu; i++) {
2781*58e6ee5fSAndroid Build Coastguard Worker 				if (handle->cpu_data[i].size)
2782*58e6ee5fSAndroid Build Coastguard Worker 					goto fail;
2783*58e6ee5fSAndroid Build Coastguard Worker 			}
2784*58e6ee5fSAndroid Build Coastguard Worker 		}
2785*58e6ee5fSAndroid Build Coastguard Worker 
2786*58e6ee5fSAndroid Build Coastguard Worker 		/* try again without mmapping, just read it directly */
2787*58e6ee5fSAndroid Build Coastguard Worker 		handle->read_page = true;
2788*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data->page = allocate_page(handle, cpu, cpu_data->offset);
2789*58e6ee5fSAndroid Build Coastguard Worker 		if (!cpu_data->page)
2790*58e6ee5fSAndroid Build Coastguard Worker 			/* Still no luck, bail! */
2791*58e6ee5fSAndroid Build Coastguard Worker 			goto fail;
2792*58e6ee5fSAndroid Build Coastguard Worker 	}
2793*58e6ee5fSAndroid Build Coastguard Worker 
2794*58e6ee5fSAndroid Build Coastguard Worker 	if (update_page_info(handle, cpu))
2795*58e6ee5fSAndroid Build Coastguard Worker 		goto fail;
2796*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->first_ts = cpu_data->timestamp;
2797*58e6ee5fSAndroid Build Coastguard Worker 
2798*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2799*58e6ee5fSAndroid Build Coastguard Worker  fail:
2800*58e6ee5fSAndroid Build Coastguard Worker 	free(cpu_data->pages);
2801*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->pages = NULL;
2802*58e6ee5fSAndroid Build Coastguard Worker 	free(cpu_data->page);
2803*58e6ee5fSAndroid Build Coastguard Worker 	cpu_data->page = NULL;
2804*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
2805*58e6ee5fSAndroid Build Coastguard Worker }
2806*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_set_ts_offset(struct tracecmd_input * handle,long long offset)2807*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_set_ts_offset(struct tracecmd_input *handle,
2808*58e6ee5fSAndroid Build Coastguard Worker 			    long long offset)
2809*58e6ee5fSAndroid Build Coastguard Worker {
2810*58e6ee5fSAndroid Build Coastguard Worker 	handle->ts_offset = offset;
2811*58e6ee5fSAndroid Build Coastguard Worker }
2812*58e6ee5fSAndroid Build Coastguard Worker 
2813*58e6ee5fSAndroid Build Coastguard Worker /**
2814*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_add_ts_offset - Add value to the offset which will be applied to the timestamps of all
2815*58e6ee5fSAndroid Build Coastguard Worker  *			    events from given trace file
2816*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle to the trace.dat file
2817*58e6ee5fSAndroid Build Coastguard Worker  * @offset: value, that will be added to the offset
2818*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_add_ts_offset(struct tracecmd_input * handle,long long offset)2819*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_add_ts_offset(struct tracecmd_input *handle,
2820*58e6ee5fSAndroid Build Coastguard Worker 			    long long offset)
2821*58e6ee5fSAndroid Build Coastguard Worker {
2822*58e6ee5fSAndroid Build Coastguard Worker 	handle->ts_offset += offset;
2823*58e6ee5fSAndroid Build Coastguard Worker }
2824*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_set_ts2secs(struct tracecmd_input * handle,unsigned long long hz)2825*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_set_ts2secs(struct tracecmd_input *handle,
2826*58e6ee5fSAndroid Build Coastguard Worker 			 unsigned long long hz)
2827*58e6ee5fSAndroid Build Coastguard Worker {
2828*58e6ee5fSAndroid Build Coastguard Worker 	double ts2secs;
2829*58e6ee5fSAndroid Build Coastguard Worker 
2830*58e6ee5fSAndroid Build Coastguard Worker 	ts2secs = (double)NSEC_PER_SEC / (double)hz;
2831*58e6ee5fSAndroid Build Coastguard Worker 	handle->ts2secs = ts2secs;
2832*58e6ee5fSAndroid Build Coastguard Worker 	handle->use_trace_clock = false;
2833*58e6ee5fSAndroid Build Coastguard Worker }
2834*58e6ee5fSAndroid Build Coastguard Worker 
tsync_offset_cmp(const void * a,const void * b)2835*58e6ee5fSAndroid Build Coastguard Worker static int tsync_offset_cmp(const void *a, const void *b)
2836*58e6ee5fSAndroid Build Coastguard Worker {
2837*58e6ee5fSAndroid Build Coastguard Worker 	struct ts_offset_sample *ts_a = (struct ts_offset_sample *)a;
2838*58e6ee5fSAndroid Build Coastguard Worker 	struct ts_offset_sample *ts_b = (struct ts_offset_sample *)b;
2839*58e6ee5fSAndroid Build Coastguard Worker 
2840*58e6ee5fSAndroid Build Coastguard Worker 	if (ts_a->time > ts_b->time)
2841*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
2842*58e6ee5fSAndroid Build Coastguard Worker 	if (ts_a->time < ts_b->time)
2843*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2844*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2845*58e6ee5fSAndroid Build Coastguard Worker }
2846*58e6ee5fSAndroid Build Coastguard Worker 
2847*58e6ee5fSAndroid Build Coastguard Worker #define safe_read(R, C)					\
2848*58e6ee5fSAndroid Build Coastguard Worker 	do {						\
2849*58e6ee5fSAndroid Build Coastguard Worker 		if ((C) > size)				\
2850*58e6ee5fSAndroid Build Coastguard Worker 			return -EFAULT;			\
2851*58e6ee5fSAndroid Build Coastguard Worker 		(R) = tep_read_number(tep, buf, (C));	\
2852*58e6ee5fSAndroid Build Coastguard Worker 		buf += (C);				\
2853*58e6ee5fSAndroid Build Coastguard Worker 		size -= (C);				\
2854*58e6ee5fSAndroid Build Coastguard Worker 	} while (0)
2855*58e6ee5fSAndroid Build Coastguard Worker 
2856*58e6ee5fSAndroid Build Coastguard Worker #define safe_read_loop(type)						\
2857*58e6ee5fSAndroid Build Coastguard Worker 	do {								\
2858*58e6ee5fSAndroid Build Coastguard Worker 		int ii;							\
2859*58e6ee5fSAndroid Build Coastguard Worker 		for (ii = 0; ii < ts_offsets->ts_samples_count; ii++)	\
2860*58e6ee5fSAndroid Build Coastguard Worker 			safe_read(ts_offsets->ts_samples[ii].type, 8);	\
2861*58e6ee5fSAndroid Build Coastguard Worker 	} while (0)
2862*58e6ee5fSAndroid Build Coastguard Worker 
tsync_cpu_offsets_load(struct tracecmd_input * handle,char * buf,int size)2863*58e6ee5fSAndroid Build Coastguard Worker static int tsync_cpu_offsets_load(struct tracecmd_input *handle, char *buf, int size)
2864*58e6ee5fSAndroid Build Coastguard Worker {
2865*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *tep = handle->pevent;
2866*58e6ee5fSAndroid Build Coastguard Worker 	struct timesync_offsets *ts_offsets;
2867*58e6ee5fSAndroid Build Coastguard Worker 	int i, j, k;
2868*58e6ee5fSAndroid Build Coastguard Worker 
2869*58e6ee5fSAndroid Build Coastguard Worker 	safe_read(handle->host.cpu_count, 4);
2870*58e6ee5fSAndroid Build Coastguard Worker 	handle->host.ts_offsets = calloc(handle->host.cpu_count,
2871*58e6ee5fSAndroid Build Coastguard Worker 					 sizeof(struct timesync_offsets));
2872*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->host.ts_offsets)
2873*58e6ee5fSAndroid Build Coastguard Worker 		return -ENOMEM;
2874*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < handle->host.cpu_count; i++) {
2875*58e6ee5fSAndroid Build Coastguard Worker 		ts_offsets = &handle->host.ts_offsets[i];
2876*58e6ee5fSAndroid Build Coastguard Worker 		safe_read(ts_offsets->ts_samples_count, 4);
2877*58e6ee5fSAndroid Build Coastguard Worker 		ts_offsets->ts_samples = calloc(ts_offsets->ts_samples_count,
2878*58e6ee5fSAndroid Build Coastguard Worker 						sizeof(struct ts_offset_sample));
2879*58e6ee5fSAndroid Build Coastguard Worker 		if (!ts_offsets->ts_samples)
2880*58e6ee5fSAndroid Build Coastguard Worker 			return -ENOMEM;
2881*58e6ee5fSAndroid Build Coastguard Worker 		safe_read_loop(time);
2882*58e6ee5fSAndroid Build Coastguard Worker 		safe_read_loop(offset);
2883*58e6ee5fSAndroid Build Coastguard Worker 		safe_read_loop(scaling);
2884*58e6ee5fSAndroid Build Coastguard Worker 	}
2885*58e6ee5fSAndroid Build Coastguard Worker 
2886*58e6ee5fSAndroid Build Coastguard Worker 	if (size > 0) {
2887*58e6ee5fSAndroid Build Coastguard Worker 		for (i = 0; i < handle->host.cpu_count; i++) {
2888*58e6ee5fSAndroid Build Coastguard Worker 			ts_offsets = &handle->host.ts_offsets[i];
2889*58e6ee5fSAndroid Build Coastguard Worker 			safe_read_loop(fraction);
2890*58e6ee5fSAndroid Build Coastguard Worker 		}
2891*58e6ee5fSAndroid Build Coastguard Worker 	}
2892*58e6ee5fSAndroid Build Coastguard Worker 
2893*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < handle->host.cpu_count; i++) {
2894*58e6ee5fSAndroid Build Coastguard Worker 		ts_offsets = &handle->host.ts_offsets[i];
2895*58e6ee5fSAndroid Build Coastguard Worker 		qsort(ts_offsets->ts_samples, ts_offsets->ts_samples_count,
2896*58e6ee5fSAndroid Build Coastguard Worker 		      sizeof(struct ts_offset_sample), tsync_offset_cmp);
2897*58e6ee5fSAndroid Build Coastguard Worker 		/* Filter possible samples with equal time */
2898*58e6ee5fSAndroid Build Coastguard Worker 		for (k = 0, j = 0; k < ts_offsets->ts_samples_count; k++) {
2899*58e6ee5fSAndroid Build Coastguard Worker 			if (k == 0 || ts_offsets->ts_samples[k].time != ts_offsets->ts_samples[k-1].time)
2900*58e6ee5fSAndroid Build Coastguard Worker 				ts_offsets->ts_samples[j++] = ts_offsets->ts_samples[k];
2901*58e6ee5fSAndroid Build Coastguard Worker 		}
2902*58e6ee5fSAndroid Build Coastguard Worker 		ts_offsets->ts_samples_count = j;
2903*58e6ee5fSAndroid Build Coastguard Worker 	}
2904*58e6ee5fSAndroid Build Coastguard Worker 
2905*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2906*58e6ee5fSAndroid Build Coastguard Worker }
2907*58e6ee5fSAndroid Build Coastguard Worker 
trace_tsync_offset_free(struct host_trace_info * host)2908*58e6ee5fSAndroid Build Coastguard Worker static void trace_tsync_offset_free(struct host_trace_info *host)
2909*58e6ee5fSAndroid Build Coastguard Worker {
2910*58e6ee5fSAndroid Build Coastguard Worker 	int i;
2911*58e6ee5fSAndroid Build Coastguard Worker 
2912*58e6ee5fSAndroid Build Coastguard Worker 	if (host->ts_offsets) {
2913*58e6ee5fSAndroid Build Coastguard Worker 		for (i = 0; i < host->cpu_count; i++)
2914*58e6ee5fSAndroid Build Coastguard Worker 			free(host->ts_offsets[i].ts_samples);
2915*58e6ee5fSAndroid Build Coastguard Worker 		free(host->ts_offsets);
2916*58e6ee5fSAndroid Build Coastguard Worker 		host->ts_offsets = NULL;
2917*58e6ee5fSAndroid Build Coastguard Worker 	}
2918*58e6ee5fSAndroid Build Coastguard Worker }
2919*58e6ee5fSAndroid Build Coastguard Worker 
trace_pid_map_cmp(const void * a,const void * b)2920*58e6ee5fSAndroid Build Coastguard Worker static int trace_pid_map_cmp(const void *a, const void *b)
2921*58e6ee5fSAndroid Build Coastguard Worker {
2922*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_proc_addr_map *m_a = (struct tracecmd_proc_addr_map *)a;
2923*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_proc_addr_map *m_b = (struct tracecmd_proc_addr_map *)b;
2924*58e6ee5fSAndroid Build Coastguard Worker 
2925*58e6ee5fSAndroid Build Coastguard Worker 	if (m_a->start > m_b->start)
2926*58e6ee5fSAndroid Build Coastguard Worker 	if (m_a->start < m_b->start)
2927*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2928*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2929*58e6ee5fSAndroid Build Coastguard Worker }
2930*58e6ee5fSAndroid Build Coastguard Worker 
procmap_free(struct pid_addr_maps * maps)2931*58e6ee5fSAndroid Build Coastguard Worker static void procmap_free(struct pid_addr_maps *maps)
2932*58e6ee5fSAndroid Build Coastguard Worker {
2933*58e6ee5fSAndroid Build Coastguard Worker 	int i;
2934*58e6ee5fSAndroid Build Coastguard Worker 
2935*58e6ee5fSAndroid Build Coastguard Worker 	if (!maps)
2936*58e6ee5fSAndroid Build Coastguard Worker 		return;
2937*58e6ee5fSAndroid Build Coastguard Worker 	if (maps->lib_maps) {
2938*58e6ee5fSAndroid Build Coastguard Worker 		for (i = 0; i < maps->nr_lib_maps; i++)
2939*58e6ee5fSAndroid Build Coastguard Worker 			free(maps->lib_maps[i].lib_name);
2940*58e6ee5fSAndroid Build Coastguard Worker 		free(maps->lib_maps);
2941*58e6ee5fSAndroid Build Coastguard Worker 	}
2942*58e6ee5fSAndroid Build Coastguard Worker 	free(maps->proc_name);
2943*58e6ee5fSAndroid Build Coastguard Worker 	free(maps);
2944*58e6ee5fSAndroid Build Coastguard Worker }
2945*58e6ee5fSAndroid Build Coastguard Worker 
trace_guests_free(struct tracecmd_input * handle)2946*58e6ee5fSAndroid Build Coastguard Worker static void trace_guests_free(struct tracecmd_input *handle)
2947*58e6ee5fSAndroid Build Coastguard Worker {
2948*58e6ee5fSAndroid Build Coastguard Worker 	struct guest_trace_info *guest;
2949*58e6ee5fSAndroid Build Coastguard Worker 
2950*58e6ee5fSAndroid Build Coastguard Worker 	while (handle->guest) {
2951*58e6ee5fSAndroid Build Coastguard Worker 		guest = handle->guest;
2952*58e6ee5fSAndroid Build Coastguard Worker 		handle->guest = handle->guest->next;
2953*58e6ee5fSAndroid Build Coastguard Worker 		free(guest->name);
2954*58e6ee5fSAndroid Build Coastguard Worker 		free(guest->cpu_pid);
2955*58e6ee5fSAndroid Build Coastguard Worker 		free(guest);
2956*58e6ee5fSAndroid Build Coastguard Worker 	}
2957*58e6ee5fSAndroid Build Coastguard Worker }
2958*58e6ee5fSAndroid Build Coastguard Worker 
trace_guest_load(struct tracecmd_input * handle,char * buf,int size)2959*58e6ee5fSAndroid Build Coastguard Worker static int trace_guest_load(struct tracecmd_input *handle, char *buf, int size)
2960*58e6ee5fSAndroid Build Coastguard Worker {
2961*58e6ee5fSAndroid Build Coastguard Worker 	struct guest_trace_info *guest = NULL;
2962*58e6ee5fSAndroid Build Coastguard Worker 	int cpu;
2963*58e6ee5fSAndroid Build Coastguard Worker 	int i;
2964*58e6ee5fSAndroid Build Coastguard Worker 
2965*58e6ee5fSAndroid Build Coastguard Worker 	guest = calloc(1, sizeof(struct guest_trace_info));
2966*58e6ee5fSAndroid Build Coastguard Worker 	if (!guest)
2967*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
2968*58e6ee5fSAndroid Build Coastguard Worker 
2969*58e6ee5fSAndroid Build Coastguard Worker 	/*
2970*58e6ee5fSAndroid Build Coastguard Worker 	 * Guest name, null terminated string
2971*58e6ee5fSAndroid Build Coastguard Worker 	 * long long (8 bytes) trace-id
2972*58e6ee5fSAndroid Build Coastguard Worker 	 * int (4 bytes) number of guest CPUs
2973*58e6ee5fSAndroid Build Coastguard Worker 	 * array of size number of guest CPUs:
2974*58e6ee5fSAndroid Build Coastguard Worker 	 *	int (4 bytes) Guest CPU id
2975*58e6ee5fSAndroid Build Coastguard Worker 	 *	int (4 bytes) Host PID, running the guest CPU
2976*58e6ee5fSAndroid Build Coastguard Worker 	 */
2977*58e6ee5fSAndroid Build Coastguard Worker 
2978*58e6ee5fSAndroid Build Coastguard Worker 	guest->name = strndup(buf, size);
2979*58e6ee5fSAndroid Build Coastguard Worker 	if (!guest->name)
2980*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
2981*58e6ee5fSAndroid Build Coastguard Worker 	buf += strlen(guest->name) + 1;
2982*58e6ee5fSAndroid Build Coastguard Worker 	size -= strlen(guest->name) + 1;
2983*58e6ee5fSAndroid Build Coastguard Worker 
2984*58e6ee5fSAndroid Build Coastguard Worker 	if (size < sizeof(long long))
2985*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
2986*58e6ee5fSAndroid Build Coastguard Worker 	guest->trace_id = tep_read_number(handle->pevent, buf, sizeof(long long));
2987*58e6ee5fSAndroid Build Coastguard Worker 	buf += sizeof(long long);
2988*58e6ee5fSAndroid Build Coastguard Worker 	size -= sizeof(long long);
2989*58e6ee5fSAndroid Build Coastguard Worker 
2990*58e6ee5fSAndroid Build Coastguard Worker 	if (size < sizeof(int))
2991*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
2992*58e6ee5fSAndroid Build Coastguard Worker 	guest->vcpu_count = tep_read_number(handle->pevent, buf, sizeof(int));
2993*58e6ee5fSAndroid Build Coastguard Worker 	buf += sizeof(int);
2994*58e6ee5fSAndroid Build Coastguard Worker 	size -= sizeof(int);
2995*58e6ee5fSAndroid Build Coastguard Worker 
2996*58e6ee5fSAndroid Build Coastguard Worker 	guest->cpu_pid = calloc(guest->vcpu_count, sizeof(int));
2997*58e6ee5fSAndroid Build Coastguard Worker 	if (!guest->cpu_pid)
2998*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
2999*58e6ee5fSAndroid Build Coastguard Worker 
3000*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < guest->vcpu_count; i++) {
3001*58e6ee5fSAndroid Build Coastguard Worker 		if (size < 2 * sizeof(int))
3002*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
3003*58e6ee5fSAndroid Build Coastguard Worker 		cpu = tep_read_number(handle->pevent, buf, sizeof(int));
3004*58e6ee5fSAndroid Build Coastguard Worker 		buf += sizeof(int);
3005*58e6ee5fSAndroid Build Coastguard Worker 		if (cpu >= guest->vcpu_count)
3006*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
3007*58e6ee5fSAndroid Build Coastguard Worker 		guest->cpu_pid[cpu] = tep_read_number(handle->pevent,
3008*58e6ee5fSAndroid Build Coastguard Worker 						      buf, sizeof(int));
3009*58e6ee5fSAndroid Build Coastguard Worker 		buf += sizeof(int);
3010*58e6ee5fSAndroid Build Coastguard Worker 		size -= 2 * sizeof(int);
3011*58e6ee5fSAndroid Build Coastguard Worker 	}
3012*58e6ee5fSAndroid Build Coastguard Worker 
3013*58e6ee5fSAndroid Build Coastguard Worker 	guest->next = handle->guest;
3014*58e6ee5fSAndroid Build Coastguard Worker 	handle->guest = guest;
3015*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
3016*58e6ee5fSAndroid Build Coastguard Worker 
3017*58e6ee5fSAndroid Build Coastguard Worker error:
3018*58e6ee5fSAndroid Build Coastguard Worker 	if (guest) {
3019*58e6ee5fSAndroid Build Coastguard Worker 		free(guest->cpu_pid);
3020*58e6ee5fSAndroid Build Coastguard Worker 		free(guest->name);
3021*58e6ee5fSAndroid Build Coastguard Worker 		free(guest);
3022*58e6ee5fSAndroid Build Coastguard Worker 	}
3023*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
3024*58e6ee5fSAndroid Build Coastguard Worker }
3025*58e6ee5fSAndroid Build Coastguard Worker 
3026*58e6ee5fSAndroid Build Coastguard Worker /* Needs to be a constant, and 4K should be good enough */
3027*58e6ee5fSAndroid Build Coastguard Worker #define STR_PROCMAP_LINE_MAX	4096
trace_pid_map_load(struct tracecmd_input * handle,char * buf)3028*58e6ee5fSAndroid Build Coastguard Worker static int trace_pid_map_load(struct tracecmd_input *handle, char *buf)
3029*58e6ee5fSAndroid Build Coastguard Worker {
3030*58e6ee5fSAndroid Build Coastguard Worker 	struct pid_addr_maps *maps = NULL;
3031*58e6ee5fSAndroid Build Coastguard Worker 	char mapname[STR_PROCMAP_LINE_MAX+1];
3032*58e6ee5fSAndroid Build Coastguard Worker 	char *line;
3033*58e6ee5fSAndroid Build Coastguard Worker 	int res;
3034*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
3035*58e6ee5fSAndroid Build Coastguard Worker 	int i;
3036*58e6ee5fSAndroid Build Coastguard Worker 
3037*58e6ee5fSAndroid Build Coastguard Worker 	maps = calloc(1, sizeof(*maps));
3038*58e6ee5fSAndroid Build Coastguard Worker 	if (!maps)
3039*58e6ee5fSAndroid Build Coastguard Worker 		return -ENOMEM;
3040*58e6ee5fSAndroid Build Coastguard Worker 
3041*58e6ee5fSAndroid Build Coastguard Worker 	ret  = -EINVAL;
3042*58e6ee5fSAndroid Build Coastguard Worker 	line = strchr(buf, '\n');
3043*58e6ee5fSAndroid Build Coastguard Worker 	if (!line)
3044*58e6ee5fSAndroid Build Coastguard Worker 		goto out_fail;
3045*58e6ee5fSAndroid Build Coastguard Worker 
3046*58e6ee5fSAndroid Build Coastguard Worker 	*line = '\0';
3047*58e6ee5fSAndroid Build Coastguard Worker 	if (strlen(buf) > STR_PROCMAP_LINE_MAX)
3048*58e6ee5fSAndroid Build Coastguard Worker 		goto out_fail;
3049*58e6ee5fSAndroid Build Coastguard Worker 
3050*58e6ee5fSAndroid Build Coastguard Worker 	res = sscanf(buf, "%x %x %"STRINGIFY(STR_PROCMAP_LINE_MAX)"s", &maps->pid, &maps->nr_lib_maps, mapname);
3051*58e6ee5fSAndroid Build Coastguard Worker 	if (res != 3)
3052*58e6ee5fSAndroid Build Coastguard Worker 		goto out_fail;
3053*58e6ee5fSAndroid Build Coastguard Worker 
3054*58e6ee5fSAndroid Build Coastguard Worker 	ret  = -ENOMEM;
3055*58e6ee5fSAndroid Build Coastguard Worker 	maps->proc_name = strdup(mapname);
3056*58e6ee5fSAndroid Build Coastguard Worker 	if (!maps->proc_name)
3057*58e6ee5fSAndroid Build Coastguard Worker 		goto out_fail;
3058*58e6ee5fSAndroid Build Coastguard Worker 
3059*58e6ee5fSAndroid Build Coastguard Worker 	maps->lib_maps = calloc(maps->nr_lib_maps, sizeof(struct tracecmd_proc_addr_map));
3060*58e6ee5fSAndroid Build Coastguard Worker 	if (!maps->lib_maps)
3061*58e6ee5fSAndroid Build Coastguard Worker 		goto out_fail;
3062*58e6ee5fSAndroid Build Coastguard Worker 
3063*58e6ee5fSAndroid Build Coastguard Worker 	buf = line + 1;
3064*58e6ee5fSAndroid Build Coastguard Worker 	line = strchr(buf, '\n');
3065*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < maps->nr_lib_maps; i++) {
3066*58e6ee5fSAndroid Build Coastguard Worker 		if (!line)
3067*58e6ee5fSAndroid Build Coastguard Worker 			break;
3068*58e6ee5fSAndroid Build Coastguard Worker 		*line = '\0';
3069*58e6ee5fSAndroid Build Coastguard Worker 		if (strlen(buf) > STR_PROCMAP_LINE_MAX)
3070*58e6ee5fSAndroid Build Coastguard Worker 			break;
3071*58e6ee5fSAndroid Build Coastguard Worker 		res = sscanf(buf, "%llx %llx %s", &maps->lib_maps[i].start,
3072*58e6ee5fSAndroid Build Coastguard Worker 			     &maps->lib_maps[i].end, mapname);
3073*58e6ee5fSAndroid Build Coastguard Worker 		if (res != 3)
3074*58e6ee5fSAndroid Build Coastguard Worker 			break;
3075*58e6ee5fSAndroid Build Coastguard Worker 		maps->lib_maps[i].lib_name = strdup(mapname);
3076*58e6ee5fSAndroid Build Coastguard Worker 		if (!maps->lib_maps[i].lib_name)
3077*58e6ee5fSAndroid Build Coastguard Worker 			goto out_fail;
3078*58e6ee5fSAndroid Build Coastguard Worker 		buf = line + 1;
3079*58e6ee5fSAndroid Build Coastguard Worker 		line = strchr(buf, '\n');
3080*58e6ee5fSAndroid Build Coastguard Worker 	}
3081*58e6ee5fSAndroid Build Coastguard Worker 
3082*58e6ee5fSAndroid Build Coastguard Worker 	ret  = -EINVAL;
3083*58e6ee5fSAndroid Build Coastguard Worker 	if (i != maps->nr_lib_maps)
3084*58e6ee5fSAndroid Build Coastguard Worker 		goto out_fail;
3085*58e6ee5fSAndroid Build Coastguard Worker 
3086*58e6ee5fSAndroid Build Coastguard Worker 	qsort(maps->lib_maps, maps->nr_lib_maps,
3087*58e6ee5fSAndroid Build Coastguard Worker 	      sizeof(*maps->lib_maps), trace_pid_map_cmp);
3088*58e6ee5fSAndroid Build Coastguard Worker 
3089*58e6ee5fSAndroid Build Coastguard Worker 	maps->next = handle->pid_maps;
3090*58e6ee5fSAndroid Build Coastguard Worker 	handle->pid_maps = maps;
3091*58e6ee5fSAndroid Build Coastguard Worker 
3092*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
3093*58e6ee5fSAndroid Build Coastguard Worker 
3094*58e6ee5fSAndroid Build Coastguard Worker out_fail:
3095*58e6ee5fSAndroid Build Coastguard Worker 	procmap_free(maps);
3096*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
3097*58e6ee5fSAndroid Build Coastguard Worker }
3098*58e6ee5fSAndroid Build Coastguard Worker 
trace_pid_map_free(struct pid_addr_maps * maps)3099*58e6ee5fSAndroid Build Coastguard Worker static void trace_pid_map_free(struct pid_addr_maps *maps)
3100*58e6ee5fSAndroid Build Coastguard Worker {
3101*58e6ee5fSAndroid Build Coastguard Worker 	struct pid_addr_maps *del;
3102*58e6ee5fSAndroid Build Coastguard Worker 
3103*58e6ee5fSAndroid Build Coastguard Worker 	while (maps) {
3104*58e6ee5fSAndroid Build Coastguard Worker 		del = maps;
3105*58e6ee5fSAndroid Build Coastguard Worker 		maps = maps->next;
3106*58e6ee5fSAndroid Build Coastguard Worker 		procmap_free(del);
3107*58e6ee5fSAndroid Build Coastguard Worker 	}
3108*58e6ee5fSAndroid Build Coastguard Worker }
3109*58e6ee5fSAndroid Build Coastguard Worker 
trace_pid_map_search(const void * a,const void * b)3110*58e6ee5fSAndroid Build Coastguard Worker static int trace_pid_map_search(const void *a, const void *b)
3111*58e6ee5fSAndroid Build Coastguard Worker {
3112*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_proc_addr_map *key = (struct tracecmd_proc_addr_map *)a;
3113*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_proc_addr_map *map = (struct tracecmd_proc_addr_map *)b;
3114*58e6ee5fSAndroid Build Coastguard Worker 
3115*58e6ee5fSAndroid Build Coastguard Worker 	if (key->start >= map->end)
3116*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
3117*58e6ee5fSAndroid Build Coastguard Worker 	if (key->start < map->start)
3118*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3119*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
3120*58e6ee5fSAndroid Build Coastguard Worker }
3121*58e6ee5fSAndroid Build Coastguard Worker 
3122*58e6ee5fSAndroid Build Coastguard Worker /**
3123*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_search_task_map - Search task memory address map
3124*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle to the trace.dat file
3125*58e6ee5fSAndroid Build Coastguard Worker  * @pid: pid of the task
3126*58e6ee5fSAndroid Build Coastguard Worker  * @addr: address from the task memory space.
3127*58e6ee5fSAndroid Build Coastguard Worker  *
3128*58e6ee5fSAndroid Build Coastguard Worker  * Map of the task memory can be saved in the trace.dat file, using the option
3129*58e6ee5fSAndroid Build Coastguard Worker  * "--proc-map". If there is such information, this API can be used to look up
3130*58e6ee5fSAndroid Build Coastguard Worker  * into this memory map to find what library is loaded at the given @addr.
3131*58e6ee5fSAndroid Build Coastguard Worker  *
3132*58e6ee5fSAndroid Build Coastguard Worker  * A pointer to struct tracecmd_proc_addr_map is returned, containing the name
3133*58e6ee5fSAndroid Build Coastguard Worker  * of the library at given task @addr and the library start and end addresses.
3134*58e6ee5fSAndroid Build Coastguard Worker  */
3135*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_proc_addr_map *
tracecmd_search_task_map(struct tracecmd_input * handle,int pid,unsigned long long addr)3136*58e6ee5fSAndroid Build Coastguard Worker tracecmd_search_task_map(struct tracecmd_input *handle,
3137*58e6ee5fSAndroid Build Coastguard Worker 			 int pid, unsigned long long addr)
3138*58e6ee5fSAndroid Build Coastguard Worker {
3139*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_proc_addr_map *lib;
3140*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_proc_addr_map key;
3141*58e6ee5fSAndroid Build Coastguard Worker 	struct pid_addr_maps *maps;
3142*58e6ee5fSAndroid Build Coastguard Worker 
3143*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle || !handle->pid_maps)
3144*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
3145*58e6ee5fSAndroid Build Coastguard Worker 
3146*58e6ee5fSAndroid Build Coastguard Worker 	maps = handle->pid_maps;
3147*58e6ee5fSAndroid Build Coastguard Worker 	while (maps) {
3148*58e6ee5fSAndroid Build Coastguard Worker 		if (maps->pid == pid)
3149*58e6ee5fSAndroid Build Coastguard Worker 			break;
3150*58e6ee5fSAndroid Build Coastguard Worker 		maps = maps->next;
3151*58e6ee5fSAndroid Build Coastguard Worker 	}
3152*58e6ee5fSAndroid Build Coastguard Worker 	if (!maps || !maps->nr_lib_maps || !maps->lib_maps)
3153*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
3154*58e6ee5fSAndroid Build Coastguard Worker 	key.start = addr;
3155*58e6ee5fSAndroid Build Coastguard Worker 	lib = bsearch(&key, maps->lib_maps, maps->nr_lib_maps,
3156*58e6ee5fSAndroid Build Coastguard Worker 		      sizeof(*maps->lib_maps), trace_pid_map_search);
3157*58e6ee5fSAndroid Build Coastguard Worker 
3158*58e6ee5fSAndroid Build Coastguard Worker 	return lib;
3159*58e6ee5fSAndroid Build Coastguard Worker }
3160*58e6ee5fSAndroid Build Coastguard Worker 
get_meta_strings_size(struct tracecmd_input * handle)3161*58e6ee5fSAndroid Build Coastguard Worker __hidden unsigned int get_meta_strings_size(struct tracecmd_input *handle)
3162*58e6ee5fSAndroid Build Coastguard Worker {
3163*58e6ee5fSAndroid Build Coastguard Worker 	return handle->strings_size;
3164*58e6ee5fSAndroid Build Coastguard Worker }
3165*58e6ee5fSAndroid Build Coastguard Worker 
get_last_option_offset(struct tracecmd_input * handle)3166*58e6ee5fSAndroid Build Coastguard Worker __hidden unsigned long long get_last_option_offset(struct tracecmd_input *handle)
3167*58e6ee5fSAndroid Build Coastguard Worker {
3168*58e6ee5fSAndroid Build Coastguard Worker 	return handle->options_last_offset;
3169*58e6ee5fSAndroid Build Coastguard Worker }
3170*58e6ee5fSAndroid Build Coastguard Worker 
handle_option_done(struct tracecmd_input * handle,char * buf,int size)3171*58e6ee5fSAndroid Build Coastguard Worker static int handle_option_done(struct tracecmd_input *handle, char *buf, int size)
3172*58e6ee5fSAndroid Build Coastguard Worker {
3173*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset;
3174*58e6ee5fSAndroid Build Coastguard Worker 
3175*58e6ee5fSAndroid Build Coastguard Worker 	if (size < 8)
3176*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3177*58e6ee5fSAndroid Build Coastguard Worker 
3178*58e6ee5fSAndroid Build Coastguard Worker 	offset = lseek64(handle->fd, 0, SEEK_CUR);
3179*58e6ee5fSAndroid Build Coastguard Worker 	if (offset >= size)
3180*58e6ee5fSAndroid Build Coastguard Worker 		handle->options_last_offset = offset - size;
3181*58e6ee5fSAndroid Build Coastguard Worker 
3182*58e6ee5fSAndroid Build Coastguard Worker 	offset = tep_read_number(handle->pevent, buf, 8);
3183*58e6ee5fSAndroid Build Coastguard Worker 	if (!offset)
3184*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
3185*58e6ee5fSAndroid Build Coastguard Worker 
3186*58e6ee5fSAndroid Build Coastguard Worker 	if (lseek64(handle->fd, offset, SEEK_SET) == (off_t)-1)
3187*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3188*58e6ee5fSAndroid Build Coastguard Worker 
3189*58e6ee5fSAndroid Build Coastguard Worker 	return handle_options(handle);
3190*58e6ee5fSAndroid Build Coastguard Worker }
3191*58e6ee5fSAndroid Build Coastguard Worker 
save_read_number(struct tep_handle * tep,char * data,int * data_size,int * read_pos,int bytes,unsigned long long * num)3192*58e6ee5fSAndroid Build Coastguard Worker static inline int save_read_number(struct tep_handle *tep, char *data, int *data_size,
3193*58e6ee5fSAndroid Build Coastguard Worker 				   int *read_pos, int bytes, unsigned long long *num)
3194*58e6ee5fSAndroid Build Coastguard Worker {
3195*58e6ee5fSAndroid Build Coastguard Worker 	if (bytes > *data_size)
3196*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3197*58e6ee5fSAndroid Build Coastguard Worker 
3198*58e6ee5fSAndroid Build Coastguard Worker 	*num = tep_read_number(tep, (data + *read_pos), bytes);
3199*58e6ee5fSAndroid Build Coastguard Worker 	*read_pos += bytes;
3200*58e6ee5fSAndroid Build Coastguard Worker 	*data_size -= bytes;
3201*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
3202*58e6ee5fSAndroid Build Coastguard Worker }
3203*58e6ee5fSAndroid Build Coastguard Worker 
save_read_string(char * data,int * data_size,int * read_pos)3204*58e6ee5fSAndroid Build Coastguard Worker static inline char *save_read_string(char *data, int *data_size, int *read_pos)
3205*58e6ee5fSAndroid Build Coastguard Worker {
3206*58e6ee5fSAndroid Build Coastguard Worker 	char *str;
3207*58e6ee5fSAndroid Build Coastguard Worker 
3208*58e6ee5fSAndroid Build Coastguard Worker 	if (*data_size < 1)
3209*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
3210*58e6ee5fSAndroid Build Coastguard Worker 
3211*58e6ee5fSAndroid Build Coastguard Worker 	str = strdup(data + *read_pos);
3212*58e6ee5fSAndroid Build Coastguard Worker 	if (!str)
3213*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
3214*58e6ee5fSAndroid Build Coastguard Worker 	*data_size -= (strlen(str) + 1);
3215*58e6ee5fSAndroid Build Coastguard Worker 	if (*data_size < 0) {
3216*58e6ee5fSAndroid Build Coastguard Worker 		free(str);
3217*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
3218*58e6ee5fSAndroid Build Coastguard Worker 	}
3219*58e6ee5fSAndroid Build Coastguard Worker 	*read_pos += (strlen(str) + 1);
3220*58e6ee5fSAndroid Build Coastguard Worker 
3221*58e6ee5fSAndroid Build Coastguard Worker 	return str;
3222*58e6ee5fSAndroid Build Coastguard Worker }
3223*58e6ee5fSAndroid Build Coastguard Worker 
handle_buffer_option(struct tracecmd_input * handle,unsigned short id,char * data,int size)3224*58e6ee5fSAndroid Build Coastguard Worker static int handle_buffer_option(struct tracecmd_input *handle,
3225*58e6ee5fSAndroid Build Coastguard Worker 				unsigned short id, char *data, int size)
3226*58e6ee5fSAndroid Build Coastguard Worker {
3227*58e6ee5fSAndroid Build Coastguard Worker 	struct input_buffer_instance *buff;
3228*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_file_data *cpu_data;
3229*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long tmp;
3230*58e6ee5fSAndroid Build Coastguard Worker 	long long max_cpu = -1;
3231*58e6ee5fSAndroid Build Coastguard Worker 	int rsize = 0;
3232*58e6ee5fSAndroid Build Coastguard Worker 	char *name;
3233*58e6ee5fSAndroid Build Coastguard Worker 	int i;
3234*58e6ee5fSAndroid Build Coastguard Worker 
3235*58e6ee5fSAndroid Build Coastguard Worker 	if (save_read_number(handle->pevent, data, &size, &rsize, 8, &tmp))
3236*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3237*58e6ee5fSAndroid Build Coastguard Worker 
3238*58e6ee5fSAndroid Build Coastguard Worker 	name = save_read_string(data, &size, &rsize);
3239*58e6ee5fSAndroid Build Coastguard Worker 	if (!name)
3240*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3241*58e6ee5fSAndroid Build Coastguard Worker 
3242*58e6ee5fSAndroid Build Coastguard Worker 	if (*name == '\0') {
3243*58e6ee5fSAndroid Build Coastguard Worker 		/* top buffer */
3244*58e6ee5fSAndroid Build Coastguard Worker 		buff = &handle->top_buffer;
3245*58e6ee5fSAndroid Build Coastguard Worker 	} else {
3246*58e6ee5fSAndroid Build Coastguard Worker 		buff = realloc(handle->buffers, sizeof(*handle->buffers) * (handle->nr_buffers + 1));
3247*58e6ee5fSAndroid Build Coastguard Worker 		if (!buff) {
3248*58e6ee5fSAndroid Build Coastguard Worker 			free(name);
3249*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3250*58e6ee5fSAndroid Build Coastguard Worker 		}
3251*58e6ee5fSAndroid Build Coastguard Worker 		handle->buffers = buff;
3252*58e6ee5fSAndroid Build Coastguard Worker 		handle->nr_buffers++;
3253*58e6ee5fSAndroid Build Coastguard Worker 
3254*58e6ee5fSAndroid Build Coastguard Worker 		buff = &handle->buffers[handle->nr_buffers - 1];
3255*58e6ee5fSAndroid Build Coastguard Worker 	}
3256*58e6ee5fSAndroid Build Coastguard Worker 	memset(buff, 0, sizeof(struct input_buffer_instance));
3257*58e6ee5fSAndroid Build Coastguard Worker 	buff->name = name;
3258*58e6ee5fSAndroid Build Coastguard Worker 	buff->offset = tmp;
3259*58e6ee5fSAndroid Build Coastguard Worker 
3260*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle))
3261*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
3262*58e6ee5fSAndroid Build Coastguard Worker 
3263*58e6ee5fSAndroid Build Coastguard Worker 	/* file sections specific data */
3264*58e6ee5fSAndroid Build Coastguard Worker 	buff->clock = save_read_string(data, &size, &rsize);
3265*58e6ee5fSAndroid Build Coastguard Worker 	if (!buff->clock)
3266*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3267*58e6ee5fSAndroid Build Coastguard Worker 
3268*58e6ee5fSAndroid Build Coastguard Worker 	if (*name == '\0' && !handle->trace_clock)
3269*58e6ee5fSAndroid Build Coastguard Worker 		handle->trace_clock = strdup(buff->clock);
3270*58e6ee5fSAndroid Build Coastguard Worker 
3271*58e6ee5fSAndroid Build Coastguard Worker 	if (id == TRACECMD_OPTION_BUFFER) {
3272*58e6ee5fSAndroid Build Coastguard Worker 		if (save_read_number(handle->pevent, data, &size, &rsize, 4, &tmp))
3273*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3274*58e6ee5fSAndroid Build Coastguard Worker 		buff->page_size = tmp;
3275*58e6ee5fSAndroid Build Coastguard Worker 
3276*58e6ee5fSAndroid Build Coastguard Worker 		if (save_read_number(handle->pevent, data, &size, &rsize, 4, &tmp))
3277*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3278*58e6ee5fSAndroid Build Coastguard Worker 		buff->cpus = tmp;
3279*58e6ee5fSAndroid Build Coastguard Worker 		if (!buff->cpus)
3280*58e6ee5fSAndroid Build Coastguard Worker 			return 0;
3281*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data = calloc(buff->cpus, sizeof(*cpu_data));
3282*58e6ee5fSAndroid Build Coastguard Worker 		if (!cpu_data)
3283*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3284*58e6ee5fSAndroid Build Coastguard Worker 		for (i = 0; i < buff->cpus; i++) {
3285*58e6ee5fSAndroid Build Coastguard Worker 			if (save_read_number(handle->pevent, data, &size, &rsize, 4, &tmp))
3286*58e6ee5fSAndroid Build Coastguard Worker 				goto fail;
3287*58e6ee5fSAndroid Build Coastguard Worker 			if ((long long)tmp > max_cpu)
3288*58e6ee5fSAndroid Build Coastguard Worker 				max_cpu = tmp;
3289*58e6ee5fSAndroid Build Coastguard Worker 			cpu_data[i].cpu = tmp;
3290*58e6ee5fSAndroid Build Coastguard Worker 			if (save_read_number(handle->pevent, data,
3291*58e6ee5fSAndroid Build Coastguard Worker 					     &size, &rsize, 8, &cpu_data[i].offset))
3292*58e6ee5fSAndroid Build Coastguard Worker 				goto fail;
3293*58e6ee5fSAndroid Build Coastguard Worker 			if (save_read_number(handle->pevent, data,
3294*58e6ee5fSAndroid Build Coastguard Worker 					     &size, &rsize, 8, &cpu_data[i].size))
3295*58e6ee5fSAndroid Build Coastguard Worker 				goto fail;
3296*58e6ee5fSAndroid Build Coastguard Worker 		}
3297*58e6ee5fSAndroid Build Coastguard Worker 		if (buff->cpus == max_cpu + 1) {
3298*58e6ee5fSAndroid Build Coastguard Worker 			/* Check to make sure cpus match the index */
3299*58e6ee5fSAndroid Build Coastguard Worker 			for (i = 0; i < buff->cpus; i++) {
3300*58e6ee5fSAndroid Build Coastguard Worker 				if (cpu_data[i].cpu != i)
3301*58e6ee5fSAndroid Build Coastguard Worker 					goto copy_buffer;
3302*58e6ee5fSAndroid Build Coastguard Worker 			}
3303*58e6ee5fSAndroid Build Coastguard Worker 			buff->cpu_data = cpu_data;
3304*58e6ee5fSAndroid Build Coastguard Worker 		} else {
3305*58e6ee5fSAndroid Build Coastguard Worker  copy_buffer:
3306*58e6ee5fSAndroid Build Coastguard Worker 			buff->cpu_data = calloc(max_cpu + 1, sizeof(*cpu_data));
3307*58e6ee5fSAndroid Build Coastguard Worker 			if (!buff->cpu_data)
3308*58e6ee5fSAndroid Build Coastguard Worker 				goto fail;
3309*58e6ee5fSAndroid Build Coastguard Worker 			for (i = 0; i < buff->cpus; i++) {
3310*58e6ee5fSAndroid Build Coastguard Worker 				if (buff->cpu_data[cpu_data[i].cpu].size) {
3311*58e6ee5fSAndroid Build Coastguard Worker 					tracecmd_warning("More than one buffer defined for CPU %d (buffer %d)\n",
3312*58e6ee5fSAndroid Build Coastguard Worker 							 cpu_data[i].cpu, i);
3313*58e6ee5fSAndroid Build Coastguard Worker 					goto fail;
3314*58e6ee5fSAndroid Build Coastguard Worker 				}
3315*58e6ee5fSAndroid Build Coastguard Worker 				buff->cpu_data[cpu_data[i].cpu] = cpu_data[i];
3316*58e6ee5fSAndroid Build Coastguard Worker 			}
3317*58e6ee5fSAndroid Build Coastguard Worker 			buff->cpus = max_cpu + 1;
3318*58e6ee5fSAndroid Build Coastguard Worker 			free(cpu_data);
3319*58e6ee5fSAndroid Build Coastguard Worker 		}
3320*58e6ee5fSAndroid Build Coastguard Worker 	} else {
3321*58e6ee5fSAndroid Build Coastguard Worker 		buff->latency = true;
3322*58e6ee5fSAndroid Build Coastguard Worker 	}
3323*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
3324*58e6ee5fSAndroid Build Coastguard Worker fail:
3325*58e6ee5fSAndroid Build Coastguard Worker 	free(cpu_data);
3326*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
3327*58e6ee5fSAndroid Build Coastguard Worker }
3328*58e6ee5fSAndroid Build Coastguard Worker 
handle_options(struct tracecmd_input * handle)3329*58e6ee5fSAndroid Build Coastguard Worker static int handle_options(struct tracecmd_input *handle)
3330*58e6ee5fSAndroid Build Coastguard Worker {
3331*58e6ee5fSAndroid Build Coastguard Worker 	long long offset;
3332*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short option;
3333*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int size;
3334*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short id, flags;
3335*58e6ee5fSAndroid Build Coastguard Worker 	char *cpustats = NULL;
3336*58e6ee5fSAndroid Build Coastguard Worker 	struct hook_list *hook;
3337*58e6ee5fSAndroid Build Coastguard Worker 	bool compress = false;
3338*58e6ee5fSAndroid Build Coastguard Worker 	char *buf;
3339*58e6ee5fSAndroid Build Coastguard Worker 	int cpus;
3340*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
3341*58e6ee5fSAndroid Build Coastguard Worker 
3342*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle)) {
3343*58e6ee5fSAndroid Build Coastguard Worker 		handle->options_start = lseek64(handle->fd, 0, SEEK_CUR);
3344*58e6ee5fSAndroid Build Coastguard Worker 	} else {
3345*58e6ee5fSAndroid Build Coastguard Worker 		if (read_section_header(handle, &id, &flags, NULL, NULL))
3346*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3347*58e6ee5fSAndroid Build Coastguard Worker 		if (id != TRACECMD_OPTION_DONE)
3348*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3349*58e6ee5fSAndroid Build Coastguard Worker 		if (flags & TRACECMD_SEC_FL_COMPRESS)
3350*58e6ee5fSAndroid Build Coastguard Worker 			compress = true;
3351*58e6ee5fSAndroid Build Coastguard Worker 	}
3352*58e6ee5fSAndroid Build Coastguard Worker 
3353*58e6ee5fSAndroid Build Coastguard Worker 	if (compress && in_uncompress_block(handle))
3354*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3355*58e6ee5fSAndroid Build Coastguard Worker 
3356*58e6ee5fSAndroid Build Coastguard Worker 	for (;;) {
3357*58e6ee5fSAndroid Build Coastguard Worker 		ret = read2(handle, &option);
3358*58e6ee5fSAndroid Build Coastguard Worker 		if (ret)
3359*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
3360*58e6ee5fSAndroid Build Coastguard Worker 
3361*58e6ee5fSAndroid Build Coastguard Worker 		if (!HAS_SECTIONS(handle) && option == TRACECMD_OPTION_DONE)
3362*58e6ee5fSAndroid Build Coastguard Worker 			break;
3363*58e6ee5fSAndroid Build Coastguard Worker 
3364*58e6ee5fSAndroid Build Coastguard Worker 		/* next 4 bytes is the size of the option */
3365*58e6ee5fSAndroid Build Coastguard Worker 		ret = read4(handle, &size);
3366*58e6ee5fSAndroid Build Coastguard Worker 		if (ret)
3367*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
3368*58e6ee5fSAndroid Build Coastguard Worker 		buf = malloc(size);
3369*58e6ee5fSAndroid Build Coastguard Worker 		if (!buf) {
3370*58e6ee5fSAndroid Build Coastguard Worker 			ret = -ENOMEM;
3371*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
3372*58e6ee5fSAndroid Build Coastguard Worker 		}
3373*58e6ee5fSAndroid Build Coastguard Worker 		ret = do_read_check(handle, buf, size);
3374*58e6ee5fSAndroid Build Coastguard Worker 		if (ret)
3375*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
3376*58e6ee5fSAndroid Build Coastguard Worker 
3377*58e6ee5fSAndroid Build Coastguard Worker 		switch (option) {
3378*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_DATE:
3379*58e6ee5fSAndroid Build Coastguard Worker 			/*
3380*58e6ee5fSAndroid Build Coastguard Worker 			 * A time has been mapped that is the
3381*58e6ee5fSAndroid Build Coastguard Worker 			 * difference between the timestamps and
3382*58e6ee5fSAndroid Build Coastguard Worker 			 * gtod. It is stored as ASCII with '0x'
3383*58e6ee5fSAndroid Build Coastguard Worker 			 * appended.
3384*58e6ee5fSAndroid Build Coastguard Worker 			 */
3385*58e6ee5fSAndroid Build Coastguard Worker 			if (handle->flags &
3386*58e6ee5fSAndroid Build Coastguard Worker 			    (TRACECMD_FL_IGNORE_DATE | TRACECMD_FL_RAW_TS))
3387*58e6ee5fSAndroid Build Coastguard Worker 				break;
3388*58e6ee5fSAndroid Build Coastguard Worker 			offset = strtoll(buf, NULL, 0);
3389*58e6ee5fSAndroid Build Coastguard Worker 			/* Convert from micro to nano */
3390*58e6ee5fSAndroid Build Coastguard Worker 			offset *= 1000;
3391*58e6ee5fSAndroid Build Coastguard Worker 			handle->ts_offset += offset;
3392*58e6ee5fSAndroid Build Coastguard Worker 			break;
3393*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_OFFSET:
3394*58e6ee5fSAndroid Build Coastguard Worker 			/*
3395*58e6ee5fSAndroid Build Coastguard Worker 			 * Similar to date option, but just adds an
3396*58e6ee5fSAndroid Build Coastguard Worker 			 * offset to the timestamp.
3397*58e6ee5fSAndroid Build Coastguard Worker 			 */
3398*58e6ee5fSAndroid Build Coastguard Worker 			if (handle->flags & TRACECMD_FL_RAW_TS)
3399*58e6ee5fSAndroid Build Coastguard Worker 				break;
3400*58e6ee5fSAndroid Build Coastguard Worker 			offset = strtoll(buf, NULL, 0);
3401*58e6ee5fSAndroid Build Coastguard Worker 			handle->ts_offset += offset;
3402*58e6ee5fSAndroid Build Coastguard Worker 			break;
3403*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_TIME_SHIFT:
3404*58e6ee5fSAndroid Build Coastguard Worker 			/*
3405*58e6ee5fSAndroid Build Coastguard Worker 			 * long long int (8 bytes) trace session ID
3406*58e6ee5fSAndroid Build Coastguard Worker 			 * int (4 bytes) protocol flags.
3407*58e6ee5fSAndroid Build Coastguard Worker 			 * int (4 bytes) CPU count.
3408*58e6ee5fSAndroid Build Coastguard Worker 			 * array of size [CPU count]:
3409*58e6ee5fSAndroid Build Coastguard Worker 			 * [
3410*58e6ee5fSAndroid Build Coastguard Worker 			 *  int (4 bytes) count of timestamp offsets.
3411*58e6ee5fSAndroid Build Coastguard Worker 			 *  long long array of size [count] of times,
3412*58e6ee5fSAndroid Build Coastguard Worker 			 *      when the offsets were calculated.
3413*58e6ee5fSAndroid Build Coastguard Worker 			 *  long long array of size [count] of timestamp offsets.
3414*58e6ee5fSAndroid Build Coastguard Worker 			 *  long long array of size [count] of timestamp scaling ratios.*
3415*58e6ee5fSAndroid Build Coastguard Worker 			 * ]
3416*58e6ee5fSAndroid Build Coastguard Worker 			 * array of size [CPU count]:
3417*58e6ee5fSAndroid Build Coastguard Worker 			 * [
3418*58e6ee5fSAndroid Build Coastguard Worker 			 *  long long array of size [count] of timestamp scaling fraction bits.*
3419*58e6ee5fSAndroid Build Coastguard Worker 			 * ]*
3420*58e6ee5fSAndroid Build Coastguard Worker 			 */
3421*58e6ee5fSAndroid Build Coastguard Worker 			if (size < 16 || (handle->flags & TRACECMD_FL_RAW_TS))
3422*58e6ee5fSAndroid Build Coastguard Worker 				break;
3423*58e6ee5fSAndroid Build Coastguard Worker 			handle->host.peer_trace_id = tep_read_number(handle->pevent,
3424*58e6ee5fSAndroid Build Coastguard Worker 								     buf, 8);
3425*58e6ee5fSAndroid Build Coastguard Worker 			handle->host.flags = tep_read_number(handle->pevent,
3426*58e6ee5fSAndroid Build Coastguard Worker 							     buf + 8, 4);
3427*58e6ee5fSAndroid Build Coastguard Worker 			ret = tsync_cpu_offsets_load(handle, buf + 12, size - 12);
3428*58e6ee5fSAndroid Build Coastguard Worker 			if (ret < 0)
3429*58e6ee5fSAndroid Build Coastguard Worker 				goto out;
3430*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_enable_tsync(handle, true);
3431*58e6ee5fSAndroid Build Coastguard Worker 			break;
3432*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_CPUSTAT:
3433*58e6ee5fSAndroid Build Coastguard Worker 			buf[size-1] = '\n';
3434*58e6ee5fSAndroid Build Coastguard Worker 			cpustats = realloc(handle->cpustats,
3435*58e6ee5fSAndroid Build Coastguard Worker 					   handle->cpustats_size + size + 1);
3436*58e6ee5fSAndroid Build Coastguard Worker 			if (!cpustats) {
3437*58e6ee5fSAndroid Build Coastguard Worker 				ret = -ENOMEM;
3438*58e6ee5fSAndroid Build Coastguard Worker 				goto out;
3439*58e6ee5fSAndroid Build Coastguard Worker 			}
3440*58e6ee5fSAndroid Build Coastguard Worker 			memcpy(cpustats + handle->cpustats_size, buf, size);
3441*58e6ee5fSAndroid Build Coastguard Worker 			handle->cpustats_size += size;
3442*58e6ee5fSAndroid Build Coastguard Worker 			cpustats[handle->cpustats_size] = 0;
3443*58e6ee5fSAndroid Build Coastguard Worker 			handle->cpustats = cpustats;
3444*58e6ee5fSAndroid Build Coastguard Worker 			break;
3445*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_BUFFER:
3446*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_BUFFER_TEXT:
3447*58e6ee5fSAndroid Build Coastguard Worker 			ret = handle_buffer_option(handle, option, buf, size);
3448*58e6ee5fSAndroid Build Coastguard Worker 			if (ret < 0)
3449*58e6ee5fSAndroid Build Coastguard Worker 				goto out;
3450*58e6ee5fSAndroid Build Coastguard Worker 			break;
3451*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_TRACECLOCK:
3452*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_parse_trace_clock(handle, buf, size);
3453*58e6ee5fSAndroid Build Coastguard Worker 			if (!handle->ts2secs)
3454*58e6ee5fSAndroid Build Coastguard Worker 				handle->use_trace_clock = true;
3455*58e6ee5fSAndroid Build Coastguard Worker 			break;
3456*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_UNAME:
3457*58e6ee5fSAndroid Build Coastguard Worker 			handle->uname = strdup(buf);
3458*58e6ee5fSAndroid Build Coastguard Worker 			break;
3459*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_VERSION:
3460*58e6ee5fSAndroid Build Coastguard Worker 			handle->version = strdup(buf);
3461*58e6ee5fSAndroid Build Coastguard Worker 			break;
3462*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_HOOK:
3463*58e6ee5fSAndroid Build Coastguard Worker 			hook = tracecmd_create_event_hook(buf);
3464*58e6ee5fSAndroid Build Coastguard Worker 			hook->next = handle->hooks;
3465*58e6ee5fSAndroid Build Coastguard Worker 			handle->hooks = hook;
3466*58e6ee5fSAndroid Build Coastguard Worker 			break;
3467*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_CPUCOUNT:
3468*58e6ee5fSAndroid Build Coastguard Worker 			cpus = *(int *)buf;
3469*58e6ee5fSAndroid Build Coastguard Worker 			handle->cpus = tep_read_number(handle->pevent, &cpus, 4);
3470*58e6ee5fSAndroid Build Coastguard Worker 			if (handle->cpus > handle->max_cpu)
3471*58e6ee5fSAndroid Build Coastguard Worker 				handle->max_cpu = handle->cpus;
3472*58e6ee5fSAndroid Build Coastguard Worker 			tep_set_cpus(handle->pevent, handle->cpus);
3473*58e6ee5fSAndroid Build Coastguard Worker 			break;
3474*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_PROCMAPS:
3475*58e6ee5fSAndroid Build Coastguard Worker 			if (buf[size-1] == '\0')
3476*58e6ee5fSAndroid Build Coastguard Worker 				trace_pid_map_load(handle, buf);
3477*58e6ee5fSAndroid Build Coastguard Worker 			break;
3478*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_TRACEID:
3479*58e6ee5fSAndroid Build Coastguard Worker 			if (size < 8)
3480*58e6ee5fSAndroid Build Coastguard Worker 				break;
3481*58e6ee5fSAndroid Build Coastguard Worker 			handle->trace_id = tep_read_number(handle->pevent,
3482*58e6ee5fSAndroid Build Coastguard Worker 							   buf, 8);
3483*58e6ee5fSAndroid Build Coastguard Worker 			break;
3484*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_GUEST:
3485*58e6ee5fSAndroid Build Coastguard Worker 			trace_guest_load(handle, buf, size);
3486*58e6ee5fSAndroid Build Coastguard Worker 			break;
3487*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_TSC2NSEC:
3488*58e6ee5fSAndroid Build Coastguard Worker 			if (size < 16 || (handle->flags & TRACECMD_FL_RAW_TS))
3489*58e6ee5fSAndroid Build Coastguard Worker 				break;
3490*58e6ee5fSAndroid Build Coastguard Worker 			handle->tsc_calc.mult = tep_read_number(handle->pevent,
3491*58e6ee5fSAndroid Build Coastguard Worker 								buf, 4);
3492*58e6ee5fSAndroid Build Coastguard Worker 			handle->tsc_calc.shift = tep_read_number(handle->pevent,
3493*58e6ee5fSAndroid Build Coastguard Worker 								 buf + 4, 4);
3494*58e6ee5fSAndroid Build Coastguard Worker 			handle->tsc_calc.offset = tep_read_number(handle->pevent,
3495*58e6ee5fSAndroid Build Coastguard Worker 								  buf + 8, 8);
3496*58e6ee5fSAndroid Build Coastguard Worker 			break;
3497*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_HEADER_INFO:
3498*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_FTRACE_EVENTS:
3499*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_EVENT_FORMATS:
3500*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_KALLSYMS:
3501*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_PRINTK:
3502*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_CMDLINES:
3503*58e6ee5fSAndroid Build Coastguard Worker 			if (size < 8)
3504*58e6ee5fSAndroid Build Coastguard Worker 				break;
3505*58e6ee5fSAndroid Build Coastguard Worker 			section_add_or_update(handle, option, -1,
3506*58e6ee5fSAndroid Build Coastguard Worker 					      tep_read_number(handle->pevent, buf, 8), 0);
3507*58e6ee5fSAndroid Build Coastguard Worker 			break;
3508*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_DONE:
3509*58e6ee5fSAndroid Build Coastguard Worker 			if (compress)
3510*58e6ee5fSAndroid Build Coastguard Worker 				in_uncompress_reset(handle);
3511*58e6ee5fSAndroid Build Coastguard Worker 			ret = handle_option_done(handle, buf, size);
3512*58e6ee5fSAndroid Build Coastguard Worker 			free(buf);
3513*58e6ee5fSAndroid Build Coastguard Worker 			return ret;
3514*58e6ee5fSAndroid Build Coastguard Worker 
3515*58e6ee5fSAndroid Build Coastguard Worker 		default:
3516*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_warning("unknown option %d", option);
3517*58e6ee5fSAndroid Build Coastguard Worker 			break;
3518*58e6ee5fSAndroid Build Coastguard Worker 		}
3519*58e6ee5fSAndroid Build Coastguard Worker 
3520*58e6ee5fSAndroid Build Coastguard Worker 		free(buf);
3521*58e6ee5fSAndroid Build Coastguard Worker 
3522*58e6ee5fSAndroid Build Coastguard Worker 	}
3523*58e6ee5fSAndroid Build Coastguard Worker 
3524*58e6ee5fSAndroid Build Coastguard Worker 	ret = 0;
3525*58e6ee5fSAndroid Build Coastguard Worker 
3526*58e6ee5fSAndroid Build Coastguard Worker out:
3527*58e6ee5fSAndroid Build Coastguard Worker 	if (compress)
3528*58e6ee5fSAndroid Build Coastguard Worker 		in_uncompress_reset(handle);
3529*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
3530*58e6ee5fSAndroid Build Coastguard Worker }
3531*58e6ee5fSAndroid Build Coastguard Worker 
read_options_type(struct tracecmd_input * handle)3532*58e6ee5fSAndroid Build Coastguard Worker static int read_options_type(struct tracecmd_input *handle)
3533*58e6ee5fSAndroid Build Coastguard Worker {
3534*58e6ee5fSAndroid Build Coastguard Worker 	char buf[10];
3535*58e6ee5fSAndroid Build Coastguard Worker 
3536*58e6ee5fSAndroid Build Coastguard Worker 	if (CHECK_READ_STATE(handle, TRACECMD_FILE_CPU_LATENCY))
3537*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
3538*58e6ee5fSAndroid Build Coastguard Worker 
3539*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, buf, 10))
3540*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3541*58e6ee5fSAndroid Build Coastguard Worker 
3542*58e6ee5fSAndroid Build Coastguard Worker 	/* check if this handles options */
3543*58e6ee5fSAndroid Build Coastguard Worker 	if (strncmp(buf, "options", 7) == 0) {
3544*58e6ee5fSAndroid Build Coastguard Worker 		if (handle_options(handle) < 0)
3545*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3546*58e6ee5fSAndroid Build Coastguard Worker 		handle->file_state = TRACECMD_FILE_OPTIONS;
3547*58e6ee5fSAndroid Build Coastguard Worker 		if (do_read_check(handle, buf, 10))
3548*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3549*58e6ee5fSAndroid Build Coastguard Worker 	}
3550*58e6ee5fSAndroid Build Coastguard Worker 
3551*58e6ee5fSAndroid Build Coastguard Worker 	/*
3552*58e6ee5fSAndroid Build Coastguard Worker 	 * Check if this is a latency report or flyrecord.
3553*58e6ee5fSAndroid Build Coastguard Worker 	 */
3554*58e6ee5fSAndroid Build Coastguard Worker 	if (strncmp(buf, "latency", 7) == 0)
3555*58e6ee5fSAndroid Build Coastguard Worker 		handle->file_state = TRACECMD_FILE_CPU_LATENCY;
3556*58e6ee5fSAndroid Build Coastguard Worker 	else if (strncmp(buf, "flyrecord", 9) == 0)
3557*58e6ee5fSAndroid Build Coastguard Worker 		handle->file_state = TRACECMD_FILE_CPU_FLYRECORD;
3558*58e6ee5fSAndroid Build Coastguard Worker 	else
3559*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3560*58e6ee5fSAndroid Build Coastguard Worker 
3561*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
3562*58e6ee5fSAndroid Build Coastguard Worker }
3563*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_latency_data_read(struct tracecmd_input * handle,char ** buf,size_t * size)3564*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_latency_data_read(struct tracecmd_input *handle, char **buf, size_t *size)
3565*58e6ee5fSAndroid Build Coastguard Worker {
3566*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_zdata *zdata = &handle->latz;
3567*58e6ee5fSAndroid Build Coastguard Worker 	void *data;
3568*58e6ee5fSAndroid Build Coastguard Worker 	int rsize;
3569*58e6ee5fSAndroid Build Coastguard Worker 	int fd = -1;
3570*58e6ee5fSAndroid Build Coastguard Worker 	int id;
3571*58e6ee5fSAndroid Build Coastguard Worker 
3572*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle || !buf || !size)
3573*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3574*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->file_state != TRACECMD_FILE_CPU_LATENCY)
3575*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3576*58e6ee5fSAndroid Build Coastguard Worker 
3577*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->cpu_compressed) {
3578*58e6ee5fSAndroid Build Coastguard Worker 		fd = handle->fd;
3579*58e6ee5fSAndroid Build Coastguard Worker 	} else if (!handle->read_zpage) {
3580*58e6ee5fSAndroid Build Coastguard Worker 		if (zdata->fd < 0)
3581*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3582*58e6ee5fSAndroid Build Coastguard Worker 		fd = zdata->fd;
3583*58e6ee5fSAndroid Build Coastguard Worker 	}
3584*58e6ee5fSAndroid Build Coastguard Worker 
3585*58e6ee5fSAndroid Build Coastguard Worker 	/* Read data from a file */
3586*58e6ee5fSAndroid Build Coastguard Worker 	if (fd >= 0) {
3587*58e6ee5fSAndroid Build Coastguard Worker 		if (!(*buf)) {
3588*58e6ee5fSAndroid Build Coastguard Worker 			*size = BUFSIZ;
3589*58e6ee5fSAndroid Build Coastguard Worker 			*buf = malloc(*size);
3590*58e6ee5fSAndroid Build Coastguard Worker 			if (!(*buf))
3591*58e6ee5fSAndroid Build Coastguard Worker 				return -1;
3592*58e6ee5fSAndroid Build Coastguard Worker 		}
3593*58e6ee5fSAndroid Build Coastguard Worker 		return do_read_fd(fd, *buf, *size);
3594*58e6ee5fSAndroid Build Coastguard Worker 	}
3595*58e6ee5fSAndroid Build Coastguard Worker 
3596*58e6ee5fSAndroid Build Coastguard Worker 	/* Uncompress data in memory */
3597*58e6ee5fSAndroid Build Coastguard Worker 	if (zdata->last_chunk >= zdata->count)
3598*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
3599*58e6ee5fSAndroid Build Coastguard Worker 
3600*58e6ee5fSAndroid Build Coastguard Worker 	id = zdata->last_chunk;
3601*58e6ee5fSAndroid Build Coastguard Worker 	if (!*buf || *size < zdata->chunks[id].size) {
3602*58e6ee5fSAndroid Build Coastguard Worker 		data = realloc(*buf, zdata->chunks[id].size);
3603*58e6ee5fSAndroid Build Coastguard Worker 		if (!data)
3604*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3605*58e6ee5fSAndroid Build Coastguard Worker 		*buf = data;
3606*58e6ee5fSAndroid Build Coastguard Worker 		*size = zdata->chunks[id].size;
3607*58e6ee5fSAndroid Build Coastguard Worker 	}
3608*58e6ee5fSAndroid Build Coastguard Worker 
3609*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_uncompress_chunk(handle->compress, &zdata->chunks[id], *buf))
3610*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3611*58e6ee5fSAndroid Build Coastguard Worker 
3612*58e6ee5fSAndroid Build Coastguard Worker 	rsize = zdata->chunks[id].size;
3613*58e6ee5fSAndroid Build Coastguard Worker 	zdata->last_chunk++;
3614*58e6ee5fSAndroid Build Coastguard Worker 	return rsize;
3615*58e6ee5fSAndroid Build Coastguard Worker }
3616*58e6ee5fSAndroid Build Coastguard Worker 
init_cpu_data(struct tracecmd_input * handle)3617*58e6ee5fSAndroid Build Coastguard Worker static int init_cpu_data(struct tracecmd_input *handle)
3618*58e6ee5fSAndroid Build Coastguard Worker {
3619*58e6ee5fSAndroid Build Coastguard Worker 	enum kbuffer_long_size long_size;
3620*58e6ee5fSAndroid Build Coastguard Worker 	enum kbuffer_endian endian;
3621*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long max_size = 0;
3622*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long pages;
3623*58e6ee5fSAndroid Build Coastguard Worker 	int cpu;
3624*58e6ee5fSAndroid Build Coastguard Worker 
3625*58e6ee5fSAndroid Build Coastguard Worker 	/* We expect this to be flyrecord */
3626*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->file_state != TRACECMD_FILE_CPU_FLYRECORD)
3627*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3628*58e6ee5fSAndroid Build Coastguard Worker 
3629*58e6ee5fSAndroid Build Coastguard Worker 	if (force_read)
3630*58e6ee5fSAndroid Build Coastguard Worker 		handle->read_page = true;
3631*58e6ee5fSAndroid Build Coastguard Worker 
3632*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->long_size == 8)
3633*58e6ee5fSAndroid Build Coastguard Worker 		long_size = KBUFFER_LSIZE_8;
3634*58e6ee5fSAndroid Build Coastguard Worker 	else
3635*58e6ee5fSAndroid Build Coastguard Worker 		long_size = KBUFFER_LSIZE_4;
3636*58e6ee5fSAndroid Build Coastguard Worker 
3637*58e6ee5fSAndroid Build Coastguard Worker 	if (tep_is_file_bigendian(handle->pevent))
3638*58e6ee5fSAndroid Build Coastguard Worker 		endian = KBUFFER_ENDIAN_BIG;
3639*58e6ee5fSAndroid Build Coastguard Worker 	else
3640*58e6ee5fSAndroid Build Coastguard Worker 		endian = KBUFFER_ENDIAN_LITTLE;
3641*58e6ee5fSAndroid Build Coastguard Worker 
3642*58e6ee5fSAndroid Build Coastguard Worker 	for (cpu = 0; cpu < handle->cpus; cpu++) {
3643*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data[cpu].compress.fd = -1;
3644*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data[cpu].kbuf = kbuffer_alloc(long_size, endian);
3645*58e6ee5fSAndroid Build Coastguard Worker 		if (!handle->cpu_data[cpu].kbuf)
3646*58e6ee5fSAndroid Build Coastguard Worker 			goto out_free;
3647*58e6ee5fSAndroid Build Coastguard Worker 		if (tep_is_old_format(handle->pevent))
3648*58e6ee5fSAndroid Build Coastguard Worker 			kbuffer_set_old_format(handle->cpu_data[cpu].kbuf);
3649*58e6ee5fSAndroid Build Coastguard Worker 
3650*58e6ee5fSAndroid Build Coastguard Worker 		if (handle->cpu_data[cpu].file_size > max_size)
3651*58e6ee5fSAndroid Build Coastguard Worker 			max_size = handle->cpu_data[cpu].file_size;
3652*58e6ee5fSAndroid Build Coastguard Worker 	}
3653*58e6ee5fSAndroid Build Coastguard Worker 
3654*58e6ee5fSAndroid Build Coastguard Worker 	/* Calculate about a meg of pages for buffering */
3655*58e6ee5fSAndroid Build Coastguard Worker 	pages = handle->page_size ? max_size / handle->page_size : 0;
3656*58e6ee5fSAndroid Build Coastguard Worker 	if (!pages)
3657*58e6ee5fSAndroid Build Coastguard Worker 		pages = 1;
3658*58e6ee5fSAndroid Build Coastguard Worker 	pages = normalize_size(pages);
3659*58e6ee5fSAndroid Build Coastguard Worker 	handle->page_map_size = handle->page_size * pages;
3660*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->page_map_size < handle->page_size)
3661*58e6ee5fSAndroid Build Coastguard Worker 		handle->page_map_size = handle->page_size;
3662*58e6ee5fSAndroid Build Coastguard Worker 
3663*58e6ee5fSAndroid Build Coastguard Worker 
3664*58e6ee5fSAndroid Build Coastguard Worker 	for (cpu = 0; cpu < handle->cpus; cpu++) {
3665*58e6ee5fSAndroid Build Coastguard Worker 		if (init_cpu(handle, cpu))
3666*58e6ee5fSAndroid Build Coastguard Worker 			goto out_free;
3667*58e6ee5fSAndroid Build Coastguard Worker 	}
3668*58e6ee5fSAndroid Build Coastguard Worker 
3669*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
3670*58e6ee5fSAndroid Build Coastguard Worker 
3671*58e6ee5fSAndroid Build Coastguard Worker  out_free:
3672*58e6ee5fSAndroid Build Coastguard Worker 	for ( ; cpu >= 0; cpu--) {
3673*58e6ee5fSAndroid Build Coastguard Worker 		free_page(handle, cpu);
3674*58e6ee5fSAndroid Build Coastguard Worker 		kbuffer_free(handle->cpu_data[cpu].kbuf);
3675*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data[cpu].kbuf = NULL;
3676*58e6ee5fSAndroid Build Coastguard Worker 	}
3677*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
3678*58e6ee5fSAndroid Build Coastguard Worker }
3679*58e6ee5fSAndroid Build Coastguard Worker 
init_latency_data(struct tracecmd_input * handle)3680*58e6ee5fSAndroid Build Coastguard Worker int init_latency_data(struct tracecmd_input *handle)
3681*58e6ee5fSAndroid Build Coastguard Worker {
3682*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long wsize;
3683*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
3684*58e6ee5fSAndroid Build Coastguard Worker 
3685*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->cpu_compressed)
3686*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
3687*58e6ee5fSAndroid Build Coastguard Worker 
3688*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->read_zpage) {
3689*58e6ee5fSAndroid Build Coastguard Worker 		handle->latz.count = tracecmd_load_chunks_info(handle->compress, &handle->latz.chunks);
3690*58e6ee5fSAndroid Build Coastguard Worker 		if (handle->latz.count < 0)
3691*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3692*58e6ee5fSAndroid Build Coastguard Worker 	} else {
3693*58e6ee5fSAndroid Build Coastguard Worker 		strcpy(handle->latz.file, COMPR_TEMP_FILE);
3694*58e6ee5fSAndroid Build Coastguard Worker 		handle->latz.fd = mkstemp(handle->latz.file);
3695*58e6ee5fSAndroid Build Coastguard Worker 		if (handle->latz.fd < 0)
3696*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3697*58e6ee5fSAndroid Build Coastguard Worker 
3698*58e6ee5fSAndroid Build Coastguard Worker 		ret = tracecmd_uncompress_copy_to(handle->compress, handle->latz.fd, NULL, &wsize);
3699*58e6ee5fSAndroid Build Coastguard Worker 		if (ret)
3700*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3701*58e6ee5fSAndroid Build Coastguard Worker 
3702*58e6ee5fSAndroid Build Coastguard Worker 		lseek64(handle->latz.fd, 0, SEEK_SET);
3703*58e6ee5fSAndroid Build Coastguard Worker 	}
3704*58e6ee5fSAndroid Build Coastguard Worker 
3705*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
3706*58e6ee5fSAndroid Build Coastguard Worker }
3707*58e6ee5fSAndroid Build Coastguard Worker 
init_buffer_cpu_data(struct tracecmd_input * handle,struct input_buffer_instance * buffer)3708*58e6ee5fSAndroid Build Coastguard Worker static int init_buffer_cpu_data(struct tracecmd_input *handle, struct input_buffer_instance *buffer)
3709*58e6ee5fSAndroid Build Coastguard Worker {
3710*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset;
3711*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
3712*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short id, flags;
3713*58e6ee5fSAndroid Build Coastguard Worker 	int cpu;
3714*58e6ee5fSAndroid Build Coastguard Worker 
3715*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->cpu_data)
3716*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3717*58e6ee5fSAndroid Build Coastguard Worker 
3718*58e6ee5fSAndroid Build Coastguard Worker 	if (lseek64(handle->fd, buffer->offset, SEEK_SET) == (off_t)-1)
3719*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3720*58e6ee5fSAndroid Build Coastguard Worker 	if (read_section_header(handle, &id, &flags, NULL, NULL))
3721*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3722*58e6ee5fSAndroid Build Coastguard Worker 	if (flags & TRACECMD_SEC_FL_COMPRESS)
3723*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_compressed = true;
3724*58e6ee5fSAndroid Build Coastguard Worker 	if (buffer->latency) {
3725*58e6ee5fSAndroid Build Coastguard Worker 		handle->file_state = TRACECMD_FILE_CPU_LATENCY;
3726*58e6ee5fSAndroid Build Coastguard Worker 		return init_latency_data(handle) == 0 ? 1 : -1;
3727*58e6ee5fSAndroid Build Coastguard Worker 	}
3728*58e6ee5fSAndroid Build Coastguard Worker 	handle->file_state = TRACECMD_FILE_CPU_FLYRECORD;
3729*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpus = buffer->cpus;
3730*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->max_cpu < handle->cpus)
3731*58e6ee5fSAndroid Build Coastguard Worker 		handle->max_cpu = handle->cpus;
3732*58e6ee5fSAndroid Build Coastguard Worker 
3733*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data = calloc(handle->cpus, sizeof(*handle->cpu_data));
3734*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->cpu_data)
3735*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3736*58e6ee5fSAndroid Build Coastguard Worker 
3737*58e6ee5fSAndroid Build Coastguard Worker 	for (cpu = 0; cpu < handle->cpus; cpu++) {
3738*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data[cpu].cpu = buffer->cpu_data[cpu].cpu;
3739*58e6ee5fSAndroid Build Coastguard Worker 		offset = buffer->cpu_data[cpu].offset;
3740*58e6ee5fSAndroid Build Coastguard Worker 		size = buffer->cpu_data[cpu].size;
3741*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data[cpu].file_offset = offset;
3742*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data[cpu].file_size = size;
3743*58e6ee5fSAndroid Build Coastguard Worker 		if (size && (offset + size > handle->total_file_size)) {
3744*58e6ee5fSAndroid Build Coastguard Worker 			/* this happens if the file got truncated */
3745*58e6ee5fSAndroid Build Coastguard Worker 			printf("File possibly truncated. "
3746*58e6ee5fSAndroid Build Coastguard Worker 				"Need at least %llu, but file size is %zu.\n",
3747*58e6ee5fSAndroid Build Coastguard Worker 				offset + size, handle->total_file_size);
3748*58e6ee5fSAndroid Build Coastguard Worker 			errno = EINVAL;
3749*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3750*58e6ee5fSAndroid Build Coastguard Worker 		}
3751*58e6ee5fSAndroid Build Coastguard Worker 	}
3752*58e6ee5fSAndroid Build Coastguard Worker 
3753*58e6ee5fSAndroid Build Coastguard Worker 	return init_cpu_data(handle);
3754*58e6ee5fSAndroid Build Coastguard Worker }
3755*58e6ee5fSAndroid Build Coastguard Worker 
read_cpu_data(struct tracecmd_input * handle)3756*58e6ee5fSAndroid Build Coastguard Worker static int read_cpu_data(struct tracecmd_input *handle)
3757*58e6ee5fSAndroid Build Coastguard Worker {
3758*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
3759*58e6ee5fSAndroid Build Coastguard Worker 	int cpus;
3760*58e6ee5fSAndroid Build Coastguard Worker 	int cpu;
3761*58e6ee5fSAndroid Build Coastguard Worker 
3762*58e6ee5fSAndroid Build Coastguard Worker 	/*
3763*58e6ee5fSAndroid Build Coastguard Worker 	 * Check if this is a latency report or not.
3764*58e6ee5fSAndroid Build Coastguard Worker 	 */
3765*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->file_state == TRACECMD_FILE_CPU_LATENCY)
3766*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
3767*58e6ee5fSAndroid Build Coastguard Worker 
3768*58e6ee5fSAndroid Build Coastguard Worker 	/* We expect this to be flyrecord */
3769*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->file_state != TRACECMD_FILE_CPU_FLYRECORD)
3770*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3771*58e6ee5fSAndroid Build Coastguard Worker 
3772*58e6ee5fSAndroid Build Coastguard Worker 	cpus = handle->cpus;
3773*58e6ee5fSAndroid Build Coastguard Worker 
3774*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data = malloc(sizeof(*handle->cpu_data) * handle->cpus);
3775*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->cpu_data)
3776*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3777*58e6ee5fSAndroid Build Coastguard Worker 	memset(handle->cpu_data, 0, sizeof(*handle->cpu_data) * handle->cpus);
3778*58e6ee5fSAndroid Build Coastguard Worker 
3779*58e6ee5fSAndroid Build Coastguard Worker 	for (cpu = 0; cpu < handle->cpus; cpu++) {
3780*58e6ee5fSAndroid Build Coastguard Worker 		unsigned long long offset;
3781*58e6ee5fSAndroid Build Coastguard Worker 
3782*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data[cpu].cpu = cpu;
3783*58e6ee5fSAndroid Build Coastguard Worker 		read8(handle, &offset);
3784*58e6ee5fSAndroid Build Coastguard Worker 		read8(handle, &size);
3785*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data[cpu].file_offset = offset;
3786*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data[cpu].file_size = size;
3787*58e6ee5fSAndroid Build Coastguard Worker 		if (size && (offset + size > handle->total_file_size)) {
3788*58e6ee5fSAndroid Build Coastguard Worker 			/* this happens if the file got truncated */
3789*58e6ee5fSAndroid Build Coastguard Worker 			printf("File possibly truncated. "
3790*58e6ee5fSAndroid Build Coastguard Worker 				"Need at least %llu, but file size is %zu.\n",
3791*58e6ee5fSAndroid Build Coastguard Worker 				offset + size, handle->total_file_size);
3792*58e6ee5fSAndroid Build Coastguard Worker 			errno = EINVAL;
3793*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3794*58e6ee5fSAndroid Build Coastguard Worker 		}
3795*58e6ee5fSAndroid Build Coastguard Worker 	}
3796*58e6ee5fSAndroid Build Coastguard Worker 
3797*58e6ee5fSAndroid Build Coastguard Worker 	/*
3798*58e6ee5fSAndroid Build Coastguard Worker 	 * It is possible that an option changed the number of CPUs.
3799*58e6ee5fSAndroid Build Coastguard Worker 	 * If that happened, then there's "empty" cpu data saved for
3800*58e6ee5fSAndroid Build Coastguard Worker 	 * backward compatibility.
3801*58e6ee5fSAndroid Build Coastguard Worker 	 */
3802*58e6ee5fSAndroid Build Coastguard Worker 	if (cpus < handle->cpus) {
3803*58e6ee5fSAndroid Build Coastguard Worker 		unsigned long long ignore;
3804*58e6ee5fSAndroid Build Coastguard Worker 		int once = 0;
3805*58e6ee5fSAndroid Build Coastguard Worker 
3806*58e6ee5fSAndroid Build Coastguard Worker 		read8(handle, &ignore); /* offset */
3807*58e6ee5fSAndroid Build Coastguard Worker 		read8(handle, &ignore); /* size */
3808*58e6ee5fSAndroid Build Coastguard Worker 		if (ignore != 0) {
3809*58e6ee5fSAndroid Build Coastguard Worker 			if (!once) {
3810*58e6ee5fSAndroid Build Coastguard Worker 				tracecmd_warning("ignored CPU data not zero size");
3811*58e6ee5fSAndroid Build Coastguard Worker 				once++;
3812*58e6ee5fSAndroid Build Coastguard Worker 			}
3813*58e6ee5fSAndroid Build Coastguard Worker 		}
3814*58e6ee5fSAndroid Build Coastguard Worker 	}
3815*58e6ee5fSAndroid Build Coastguard Worker 
3816*58e6ee5fSAndroid Build Coastguard Worker 	return init_cpu_data(handle);
3817*58e6ee5fSAndroid Build Coastguard Worker }
3818*58e6ee5fSAndroid Build Coastguard Worker 
read_data_and_size(struct tracecmd_input * handle,char ** data,unsigned long long * size)3819*58e6ee5fSAndroid Build Coastguard Worker static int read_data_and_size(struct tracecmd_input *handle,
3820*58e6ee5fSAndroid Build Coastguard Worker 				     char **data, unsigned long long *size)
3821*58e6ee5fSAndroid Build Coastguard Worker {
3822*58e6ee5fSAndroid Build Coastguard Worker 	if (read8(handle, size) < 0)
3823*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3824*58e6ee5fSAndroid Build Coastguard Worker 	*data = malloc(*size + 1);
3825*58e6ee5fSAndroid Build Coastguard Worker 	if (!*data)
3826*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3827*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, *data, *size)) {
3828*58e6ee5fSAndroid Build Coastguard Worker 		free(*data);
3829*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3830*58e6ee5fSAndroid Build Coastguard Worker 	}
3831*58e6ee5fSAndroid Build Coastguard Worker 
3832*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
3833*58e6ee5fSAndroid Build Coastguard Worker }
3834*58e6ee5fSAndroid Build Coastguard Worker 
read_and_parse_cmdlines(struct tracecmd_input * handle)3835*58e6ee5fSAndroid Build Coastguard Worker static int read_and_parse_cmdlines(struct tracecmd_input *handle)
3836*58e6ee5fSAndroid Build Coastguard Worker {
3837*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = handle->pevent;
3838*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
3839*58e6ee5fSAndroid Build Coastguard Worker 	char *cmdlines;
3840*58e6ee5fSAndroid Build Coastguard Worker 
3841*58e6ee5fSAndroid Build Coastguard Worker 	if (CHECK_READ_STATE(handle, TRACECMD_FILE_CMD_LINES))
3842*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
3843*58e6ee5fSAndroid Build Coastguard Worker 
3844*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle))
3845*58e6ee5fSAndroid Build Coastguard Worker 		section_add_or_update(handle, TRACECMD_OPTION_CMDLINES, 0, 0,
3846*58e6ee5fSAndroid Build Coastguard Worker 				      lseek64(handle->fd, 0, SEEK_CUR));
3847*58e6ee5fSAndroid Build Coastguard Worker 
3848*58e6ee5fSAndroid Build Coastguard Worker 
3849*58e6ee5fSAndroid Build Coastguard Worker 	if (read_data_and_size(handle, &cmdlines, &size) < 0)
3850*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3851*58e6ee5fSAndroid Build Coastguard Worker 	cmdlines[size] = 0;
3852*58e6ee5fSAndroid Build Coastguard Worker 	tep_parse_saved_cmdlines(pevent, cmdlines);
3853*58e6ee5fSAndroid Build Coastguard Worker 	free(cmdlines);
3854*58e6ee5fSAndroid Build Coastguard Worker 
3855*58e6ee5fSAndroid Build Coastguard Worker 	handle->file_state = TRACECMD_FILE_CMD_LINES;
3856*58e6ee5fSAndroid Build Coastguard Worker 
3857*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
3858*58e6ee5fSAndroid Build Coastguard Worker }
3859*58e6ee5fSAndroid Build Coastguard Worker 
extract_trace_clock(struct tracecmd_input * handle,char * line)3860*58e6ee5fSAndroid Build Coastguard Worker static void extract_trace_clock(struct tracecmd_input *handle, char *line)
3861*58e6ee5fSAndroid Build Coastguard Worker {
3862*58e6ee5fSAndroid Build Coastguard Worker 	char *clock = NULL;
3863*58e6ee5fSAndroid Build Coastguard Worker 	char *next = NULL;
3864*58e6ee5fSAndroid Build Coastguard Worker 	char *data;
3865*58e6ee5fSAndroid Build Coastguard Worker 
3866*58e6ee5fSAndroid Build Coastguard Worker 	data = strtok_r(line, "[]", &next);
3867*58e6ee5fSAndroid Build Coastguard Worker 	sscanf(data, "%ms", &clock);
3868*58e6ee5fSAndroid Build Coastguard Worker 	/* TODO: report if it fails to allocate */
3869*58e6ee5fSAndroid Build Coastguard Worker 	handle->trace_clock = clock;
3870*58e6ee5fSAndroid Build Coastguard Worker 
3871*58e6ee5fSAndroid Build Coastguard Worker 	if (!clock)
3872*58e6ee5fSAndroid Build Coastguard Worker 		return;
3873*58e6ee5fSAndroid Build Coastguard Worker 
3874*58e6ee5fSAndroid Build Coastguard Worker 	/* Clear usecs if raw timestamps are requested */
3875*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->flags & TRACECMD_FL_RAW_TS)
3876*58e6ee5fSAndroid Build Coastguard Worker 		handle->flags &= ~TRACECMD_FL_IN_USECS;
3877*58e6ee5fSAndroid Build Coastguard Worker 
3878*58e6ee5fSAndroid Build Coastguard Worker 	/* Clear usecs if not one of the specified clocks */
3879*58e6ee5fSAndroid Build Coastguard Worker 	if (strcmp(clock, "local") && strcmp(clock, "global") &&
3880*58e6ee5fSAndroid Build Coastguard Worker 	    strcmp(clock, "uptime") && strcmp(clock, "perf") &&
3881*58e6ee5fSAndroid Build Coastguard Worker 	    strncmp(clock, "mono", 4) && strcmp(clock, TSCNSEC_CLOCK) &&
3882*58e6ee5fSAndroid Build Coastguard Worker 	    strcmp(clock, "tai"))
3883*58e6ee5fSAndroid Build Coastguard Worker 		handle->flags &= ~TRACECMD_FL_IN_USECS;
3884*58e6ee5fSAndroid Build Coastguard Worker }
3885*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_parse_trace_clock(struct tracecmd_input * handle,char * file,int size __maybe_unused)3886*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_parse_trace_clock(struct tracecmd_input *handle,
3887*58e6ee5fSAndroid Build Coastguard Worker 				char *file, int size __maybe_unused)
3888*58e6ee5fSAndroid Build Coastguard Worker {
3889*58e6ee5fSAndroid Build Coastguard Worker 	char *line;
3890*58e6ee5fSAndroid Build Coastguard Worker 	char *next = NULL;
3891*58e6ee5fSAndroid Build Coastguard Worker 
3892*58e6ee5fSAndroid Build Coastguard Worker 	line = strtok_r(file, " ", &next);
3893*58e6ee5fSAndroid Build Coastguard Worker 	while (line) {
3894*58e6ee5fSAndroid Build Coastguard Worker 		/* current trace_clock is shown as "[local]". */
3895*58e6ee5fSAndroid Build Coastguard Worker 		if (*line == '[')
3896*58e6ee5fSAndroid Build Coastguard Worker 			return extract_trace_clock(handle, line);
3897*58e6ee5fSAndroid Build Coastguard Worker 		line = strtok_r(NULL, " ", &next);
3898*58e6ee5fSAndroid Build Coastguard Worker 	}
3899*58e6ee5fSAndroid Build Coastguard Worker }
3900*58e6ee5fSAndroid Build Coastguard Worker 
read_and_parse_trace_clock(struct tracecmd_input * handle,struct tep_handle * pevent)3901*58e6ee5fSAndroid Build Coastguard Worker static int read_and_parse_trace_clock(struct tracecmd_input *handle,
3902*58e6ee5fSAndroid Build Coastguard Worker 							struct tep_handle *pevent)
3903*58e6ee5fSAndroid Build Coastguard Worker {
3904*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
3905*58e6ee5fSAndroid Build Coastguard Worker 	char *trace_clock;
3906*58e6ee5fSAndroid Build Coastguard Worker 
3907*58e6ee5fSAndroid Build Coastguard Worker 	if (read_data_and_size(handle, &trace_clock, &size) < 0)
3908*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
3909*58e6ee5fSAndroid Build Coastguard Worker 	trace_clock[size] = 0;
3910*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_parse_trace_clock(handle, trace_clock, size);
3911*58e6ee5fSAndroid Build Coastguard Worker 	free(trace_clock);
3912*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
3913*58e6ee5fSAndroid Build Coastguard Worker }
3914*58e6ee5fSAndroid Build Coastguard Worker 
init_data_v6(struct tracecmd_input * handle)3915*58e6ee5fSAndroid Build Coastguard Worker static int init_data_v6(struct tracecmd_input *handle)
3916*58e6ee5fSAndroid Build Coastguard Worker {
3917*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = handle->pevent;
3918*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
3919*58e6ee5fSAndroid Build Coastguard Worker 
3920*58e6ee5fSAndroid Build Coastguard Worker 	ret = read_cpu_data(handle);
3921*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
3922*58e6ee5fSAndroid Build Coastguard Worker 		return ret;
3923*58e6ee5fSAndroid Build Coastguard Worker 
3924*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->use_trace_clock) {
3925*58e6ee5fSAndroid Build Coastguard Worker 		/*
3926*58e6ee5fSAndroid Build Coastguard Worker 		 * There was a bug in the original setting of
3927*58e6ee5fSAndroid Build Coastguard Worker 		 * the trace_clock file which let it get
3928*58e6ee5fSAndroid Build Coastguard Worker 		 * corrupted. If it fails to read, force local
3929*58e6ee5fSAndroid Build Coastguard Worker 		 * clock.
3930*58e6ee5fSAndroid Build Coastguard Worker 		 */
3931*58e6ee5fSAndroid Build Coastguard Worker 		if (read_and_parse_trace_clock(handle, pevent) < 0) {
3932*58e6ee5fSAndroid Build Coastguard Worker 			char clock[] = "[local]";
3933*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_warning("File has trace_clock bug, using local clock");
3934*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_parse_trace_clock(handle, clock, 8);
3935*58e6ee5fSAndroid Build Coastguard Worker 		}
3936*58e6ee5fSAndroid Build Coastguard Worker 	}
3937*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
3938*58e6ee5fSAndroid Build Coastguard Worker }
3939*58e6ee5fSAndroid Build Coastguard Worker 
init_data(struct tracecmd_input * handle)3940*58e6ee5fSAndroid Build Coastguard Worker static int init_data(struct tracecmd_input *handle)
3941*58e6ee5fSAndroid Build Coastguard Worker {
3942*58e6ee5fSAndroid Build Coastguard Worker 	return init_buffer_cpu_data(handle, &handle->top_buffer);
3943*58e6ee5fSAndroid Build Coastguard Worker }
3944*58e6ee5fSAndroid Build Coastguard Worker 
3945*58e6ee5fSAndroid Build Coastguard Worker /**
3946*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_init_data - prepare reading the data from trace.dat
3947*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
3948*58e6ee5fSAndroid Build Coastguard Worker  *
3949*58e6ee5fSAndroid Build Coastguard Worker  * This prepares reading the data from trace.dat. This is called
3950*58e6ee5fSAndroid Build Coastguard Worker  * after tracecmd_read_headers() and before tracecmd_read_data().
3951*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_init_data(struct tracecmd_input * handle)3952*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_init_data(struct tracecmd_input *handle)
3953*58e6ee5fSAndroid Build Coastguard Worker {
3954*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
3955*58e6ee5fSAndroid Build Coastguard Worker 
3956*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle))
3957*58e6ee5fSAndroid Build Coastguard Worker 		ret = init_data_v6(handle);
3958*58e6ee5fSAndroid Build Coastguard Worker 	else
3959*58e6ee5fSAndroid Build Coastguard Worker 		ret = init_data(handle);
3960*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_blk_hack(handle);
3961*58e6ee5fSAndroid Build Coastguard Worker 
3962*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
3963*58e6ee5fSAndroid Build Coastguard Worker }
3964*58e6ee5fSAndroid Build Coastguard Worker 
3965*58e6ee5fSAndroid Build Coastguard Worker /**
3966*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_make_pipe - Have the handle read a pipe instead of a file
3967*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle to read from a pipe
3968*58e6ee5fSAndroid Build Coastguard Worker  * @cpu: the cpu that the pipe represents
3969*58e6ee5fSAndroid Build Coastguard Worker  * @fd: the read end of the pipe
3970*58e6ee5fSAndroid Build Coastguard Worker  * @cpus: the total number of cpus for this handle
3971*58e6ee5fSAndroid Build Coastguard Worker  *
3972*58e6ee5fSAndroid Build Coastguard Worker  * In order to stream data from the binary trace files and produce
3973*58e6ee5fSAndroid Build Coastguard Worker  * output or analyze the data, a tracecmd_input descriptor needs to
3974*58e6ee5fSAndroid Build Coastguard Worker  * be created, and then converted into a form that can act on a
3975*58e6ee5fSAndroid Build Coastguard Worker  * pipe.
3976*58e6ee5fSAndroid Build Coastguard Worker  *
3977*58e6ee5fSAndroid Build Coastguard Worker  * Note, there are limitations to what this descriptor can do.
3978*58e6ee5fSAndroid Build Coastguard Worker  * Most notibly, it can not read backwards. Once a page is read
3979*58e6ee5fSAndroid Build Coastguard Worker  * it can not be read at a later time (except if a record is attached
3980*58e6ee5fSAndroid Build Coastguard Worker  * to it and is holding the page ref).
3981*58e6ee5fSAndroid Build Coastguard Worker  *
3982*58e6ee5fSAndroid Build Coastguard Worker  * It is expected that the handle has already been created and
3983*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_read_headers() has run on it.
3984*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_make_pipe(struct tracecmd_input * handle,int cpu,int fd,int cpus)3985*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_make_pipe(struct tracecmd_input *handle, int cpu, int fd, int cpus)
3986*58e6ee5fSAndroid Build Coastguard Worker {
3987*58e6ee5fSAndroid Build Coastguard Worker 	enum kbuffer_long_size long_size;
3988*58e6ee5fSAndroid Build Coastguard Worker 	enum kbuffer_endian endian;
3989*58e6ee5fSAndroid Build Coastguard Worker 
3990*58e6ee5fSAndroid Build Coastguard Worker 	handle->read_page = true;
3991*58e6ee5fSAndroid Build Coastguard Worker 	handle->use_pipe = true;
3992*58e6ee5fSAndroid Build Coastguard Worker 
3993*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->cpus) {
3994*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpus = cpus;
3995*58e6ee5fSAndroid Build Coastguard Worker 		handle->cpu_data = malloc(sizeof(*handle->cpu_data) * handle->cpus);
3996*58e6ee5fSAndroid Build Coastguard Worker 		if (!handle->cpu_data)
3997*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
3998*58e6ee5fSAndroid Build Coastguard Worker 	}
3999*58e6ee5fSAndroid Build Coastguard Worker 
4000*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu >= handle->cpus)
4001*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4002*58e6ee5fSAndroid Build Coastguard Worker 
4003*58e6ee5fSAndroid Build Coastguard Worker 
4004*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->long_size == 8)
4005*58e6ee5fSAndroid Build Coastguard Worker 		long_size = KBUFFER_LSIZE_8;
4006*58e6ee5fSAndroid Build Coastguard Worker 	else
4007*58e6ee5fSAndroid Build Coastguard Worker 		long_size = KBUFFER_LSIZE_4;
4008*58e6ee5fSAndroid Build Coastguard Worker 
4009*58e6ee5fSAndroid Build Coastguard Worker 	if (tep_is_file_bigendian(handle->pevent))
4010*58e6ee5fSAndroid Build Coastguard Worker 		endian = KBUFFER_ENDIAN_BIG;
4011*58e6ee5fSAndroid Build Coastguard Worker 	else
4012*58e6ee5fSAndroid Build Coastguard Worker 		endian = KBUFFER_ENDIAN_LITTLE;
4013*58e6ee5fSAndroid Build Coastguard Worker 
4014*58e6ee5fSAndroid Build Coastguard Worker 	memset(&handle->cpu_data[cpu], 0, sizeof(handle->cpu_data[cpu]));
4015*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].pipe_fd = fd;
4016*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].cpu = cpu;
4017*58e6ee5fSAndroid Build Coastguard Worker 
4018*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].kbuf = kbuffer_alloc(long_size, endian);
4019*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->cpu_data[cpu].kbuf)
4020*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4021*58e6ee5fSAndroid Build Coastguard Worker 	if (tep_is_old_format(handle->pevent))
4022*58e6ee5fSAndroid Build Coastguard Worker 		kbuffer_set_old_format(handle->cpu_data[cpu].kbuf);
4023*58e6ee5fSAndroid Build Coastguard Worker 
4024*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].file_offset = 0;
4025*58e6ee5fSAndroid Build Coastguard Worker 	handle->cpu_data[cpu].file_size = -1;
4026*58e6ee5fSAndroid Build Coastguard Worker 
4027*58e6ee5fSAndroid Build Coastguard Worker 	init_cpu(handle, cpu);
4028*58e6ee5fSAndroid Build Coastguard Worker 
4029*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4030*58e6ee5fSAndroid Build Coastguard Worker }
4031*58e6ee5fSAndroid Build Coastguard Worker 
4032*58e6ee5fSAndroid Build Coastguard Worker /**
4033*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_print_events - print the events that are stored in trace.dat
4034*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
4035*58e6ee5fSAndroid Build Coastguard Worker  * @regex: regex of events to print (NULL is all events)
4036*58e6ee5fSAndroid Build Coastguard Worker  *
4037*58e6ee5fSAndroid Build Coastguard Worker  * This is a debugging routine to print out the events that
4038*58e6ee5fSAndroid Build Coastguard Worker  * are stored in a given trace.dat file.
4039*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_print_events(struct tracecmd_input * handle,const char * regex)4040*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_print_events(struct tracecmd_input *handle, const char *regex)
4041*58e6ee5fSAndroid Build Coastguard Worker {
4042*58e6ee5fSAndroid Build Coastguard Worker 	if (!regex)
4043*58e6ee5fSAndroid Build Coastguard Worker 		regex = ".*";
4044*58e6ee5fSAndroid Build Coastguard Worker 
4045*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle))
4046*58e6ee5fSAndroid Build Coastguard Worker 		read_headers_v6(handle, TRACECMD_FILE_ALL_EVENTS, regex);
4047*58e6ee5fSAndroid Build Coastguard Worker 
4048*58e6ee5fSAndroid Build Coastguard Worker 	read_headers(handle, regex);
4049*58e6ee5fSAndroid Build Coastguard Worker }
4050*58e6ee5fSAndroid Build Coastguard Worker 
4051*58e6ee5fSAndroid Build Coastguard Worker /* Show the cpu data stats */
show_cpu_stats(struct tracecmd_input * handle)4052*58e6ee5fSAndroid Build Coastguard Worker static void show_cpu_stats(struct tracecmd_input *handle)
4053*58e6ee5fSAndroid Build Coastguard Worker {
4054*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data;
4055*58e6ee5fSAndroid Build Coastguard Worker 	int i;
4056*58e6ee5fSAndroid Build Coastguard Worker 
4057*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < handle->cpus; i++) {
4058*58e6ee5fSAndroid Build Coastguard Worker 		cpu_data = &handle->cpu_data[i];
4059*58e6ee5fSAndroid Build Coastguard Worker 		printf("CPU%d data recorded at offset=0x%llx\n",
4060*58e6ee5fSAndroid Build Coastguard Worker 		       i, cpu_data->file_offset);
4061*58e6ee5fSAndroid Build Coastguard Worker 		printf("    %lld bytes in size\n", cpu_data->file_size);
4062*58e6ee5fSAndroid Build Coastguard Worker 	}
4063*58e6ee5fSAndroid Build Coastguard Worker }
4064*58e6ee5fSAndroid Build Coastguard Worker 
4065*58e6ee5fSAndroid Build Coastguard Worker /**
4066*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_print_stats - prints the stats recorded in the options.
4067*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
4068*58e6ee5fSAndroid Build Coastguard Worker  *
4069*58e6ee5fSAndroid Build Coastguard Worker  * Looks for the option TRACECMD_OPTION_CPUSTAT and prints out what's
4070*58e6ee5fSAndroid Build Coastguard Worker  * stored there, if it is found. Otherwise it prints that none were found.
4071*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_print_stats(struct tracecmd_input * handle)4072*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_print_stats(struct tracecmd_input *handle)
4073*58e6ee5fSAndroid Build Coastguard Worker {
4074*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->cpustats)
4075*58e6ee5fSAndroid Build Coastguard Worker 		printf("%s\n", handle->cpustats);
4076*58e6ee5fSAndroid Build Coastguard Worker 	else
4077*58e6ee5fSAndroid Build Coastguard Worker 		printf(" No stats in this file\n");
4078*58e6ee5fSAndroid Build Coastguard Worker 
4079*58e6ee5fSAndroid Build Coastguard Worker 	show_cpu_stats(handle);
4080*58e6ee5fSAndroid Build Coastguard Worker }
4081*58e6ee5fSAndroid Build Coastguard Worker 
4082*58e6ee5fSAndroid Build Coastguard Worker /**
4083*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_print_uname - prints the recorded uname if it was recorded
4084*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
4085*58e6ee5fSAndroid Build Coastguard Worker  *
4086*58e6ee5fSAndroid Build Coastguard Worker  * Looks for the option TRACECMD_OPTION_UNAME and prints out what's
4087*58e6ee5fSAndroid Build Coastguard Worker  * stored there, if it is found. Otherwise it prints that none were found.
4088*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_print_uname(struct tracecmd_input * handle)4089*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_print_uname(struct tracecmd_input *handle)
4090*58e6ee5fSAndroid Build Coastguard Worker {
4091*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->uname)
4092*58e6ee5fSAndroid Build Coastguard Worker 		printf("%s\n", handle->uname);
4093*58e6ee5fSAndroid Build Coastguard Worker 	else
4094*58e6ee5fSAndroid Build Coastguard Worker 		printf(" uname was not recorded in this file\n");
4095*58e6ee5fSAndroid Build Coastguard Worker }
4096*58e6ee5fSAndroid Build Coastguard Worker 
4097*58e6ee5fSAndroid Build Coastguard Worker /**
4098*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_print_uname - prints the recorded uname if it was recorded
4099*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
4100*58e6ee5fSAndroid Build Coastguard Worker  *
4101*58e6ee5fSAndroid Build Coastguard Worker  * Looks for the option TRACECMD_OPTION_VERSION and prints out what's
4102*58e6ee5fSAndroid Build Coastguard Worker  * stored there, if it is found. Otherwise it prints that none were found.
4103*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_print_version(struct tracecmd_input * handle)4104*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_print_version(struct tracecmd_input *handle)
4105*58e6ee5fSAndroid Build Coastguard Worker {
4106*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->version)
4107*58e6ee5fSAndroid Build Coastguard Worker 		printf("%s\n", handle->version);
4108*58e6ee5fSAndroid Build Coastguard Worker 	else
4109*58e6ee5fSAndroid Build Coastguard Worker 		printf(" version was not recorded in this file\n");
4110*58e6ee5fSAndroid Build Coastguard Worker }
4111*58e6ee5fSAndroid Build Coastguard Worker 
4112*58e6ee5fSAndroid Build Coastguard Worker /**
4113*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_hooks - return the event hooks that were used in record
4114*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
4115*58e6ee5fSAndroid Build Coastguard Worker  *
4116*58e6ee5fSAndroid Build Coastguard Worker  * If trace-cmd record used -H to save hooks, they are parsed and
4117*58e6ee5fSAndroid Build Coastguard Worker  * presented as hooks here.
4118*58e6ee5fSAndroid Build Coastguard Worker  *
4119*58e6ee5fSAndroid Build Coastguard Worker  * Returns the hook list (do not free it, they are freed on close)
4120*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_hooks(struct tracecmd_input * handle)4121*58e6ee5fSAndroid Build Coastguard Worker struct hook_list *tracecmd_hooks(struct tracecmd_input *handle)
4122*58e6ee5fSAndroid Build Coastguard Worker {
4123*58e6ee5fSAndroid Build Coastguard Worker 	return handle->hooks;
4124*58e6ee5fSAndroid Build Coastguard Worker }
4125*58e6ee5fSAndroid Build Coastguard Worker 
init_metadata_strings(struct tracecmd_input * handle,int size)4126*58e6ee5fSAndroid Build Coastguard Worker static int init_metadata_strings(struct tracecmd_input *handle, int size)
4127*58e6ee5fSAndroid Build Coastguard Worker {
4128*58e6ee5fSAndroid Build Coastguard Worker 	char *tmp;
4129*58e6ee5fSAndroid Build Coastguard Worker 
4130*58e6ee5fSAndroid Build Coastguard Worker 	tmp = realloc(handle->strings, handle->strings_size + size);
4131*58e6ee5fSAndroid Build Coastguard Worker 	if (!tmp)
4132*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4133*58e6ee5fSAndroid Build Coastguard Worker 
4134*58e6ee5fSAndroid Build Coastguard Worker 	handle->strings = tmp;
4135*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, handle->strings + handle->strings_size, size))
4136*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4137*58e6ee5fSAndroid Build Coastguard Worker 
4138*58e6ee5fSAndroid Build Coastguard Worker 	handle->strings_size += size;
4139*58e6ee5fSAndroid Build Coastguard Worker 
4140*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4141*58e6ee5fSAndroid Build Coastguard Worker }
4142*58e6ee5fSAndroid Build Coastguard Worker 
read_metadata_strings(struct tracecmd_input * handle)4143*58e6ee5fSAndroid Build Coastguard Worker static int read_metadata_strings(struct tracecmd_input *handle)
4144*58e6ee5fSAndroid Build Coastguard Worker {
4145*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short flags;
4146*58e6ee5fSAndroid Build Coastguard Worker 	int found = 0;
4147*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short id;
4148*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int csize, rsize;
4149*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
4150*58e6ee5fSAndroid Build Coastguard Worker 	off64_t offset;
4151*58e6ee5fSAndroid Build Coastguard Worker 
4152*58e6ee5fSAndroid Build Coastguard Worker 	offset = lseek64(handle->fd, 0, SEEK_CUR);
4153*58e6ee5fSAndroid Build Coastguard Worker 	do {
4154*58e6ee5fSAndroid Build Coastguard Worker 		if (read_section_header(handle, &id, &flags, &size, NULL))
4155*58e6ee5fSAndroid Build Coastguard Worker 			break;
4156*58e6ee5fSAndroid Build Coastguard Worker 		if (id == TRACECMD_OPTION_STRINGS) {
4157*58e6ee5fSAndroid Build Coastguard Worker 			found++;
4158*58e6ee5fSAndroid Build Coastguard Worker 			if ((flags & TRACECMD_SEC_FL_COMPRESS)) {
4159*58e6ee5fSAndroid Build Coastguard Worker 				read4(handle, &csize);
4160*58e6ee5fSAndroid Build Coastguard Worker 				read4(handle, &rsize);
4161*58e6ee5fSAndroid Build Coastguard Worker 				do_lseek(handle, -8, SEEK_CUR);
4162*58e6ee5fSAndroid Build Coastguard Worker 				if (in_uncompress_block(handle))
4163*58e6ee5fSAndroid Build Coastguard Worker 					break;
4164*58e6ee5fSAndroid Build Coastguard Worker 			} else {
4165*58e6ee5fSAndroid Build Coastguard Worker 				rsize = size;
4166*58e6ee5fSAndroid Build Coastguard Worker 			}
4167*58e6ee5fSAndroid Build Coastguard Worker 			init_metadata_strings(handle, rsize);
4168*58e6ee5fSAndroid Build Coastguard Worker 			if (flags & TRACECMD_SEC_FL_COMPRESS)
4169*58e6ee5fSAndroid Build Coastguard Worker 				in_uncompress_reset(handle);
4170*58e6ee5fSAndroid Build Coastguard Worker 		} else {
4171*58e6ee5fSAndroid Build Coastguard Worker 			if (lseek64(handle->fd, size, SEEK_CUR) == (off_t)-1)
4172*58e6ee5fSAndroid Build Coastguard Worker 				break;
4173*58e6ee5fSAndroid Build Coastguard Worker 		}
4174*58e6ee5fSAndroid Build Coastguard Worker 	} while (1);
4175*58e6ee5fSAndroid Build Coastguard Worker 
4176*58e6ee5fSAndroid Build Coastguard Worker 	if (lseek64(handle->fd, offset, SEEK_SET) == (off_t)-1)
4177*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4178*58e6ee5fSAndroid Build Coastguard Worker 
4179*58e6ee5fSAndroid Build Coastguard Worker 	return found ? 0 : -1;
4180*58e6ee5fSAndroid Build Coastguard Worker }
4181*58e6ee5fSAndroid Build Coastguard Worker 
4182*58e6ee5fSAndroid Build Coastguard Worker /**
4183*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_alloc_fd - create a tracecmd_input handle from a file descriptor
4184*58e6ee5fSAndroid Build Coastguard Worker  * @fd: the file descriptor for the trace.dat file
4185*58e6ee5fSAndroid Build Coastguard Worker  * @flags: bitmask of enum tracecmd_open_flags
4186*58e6ee5fSAndroid Build Coastguard Worker  *
4187*58e6ee5fSAndroid Build Coastguard Worker  * Allocate a tracecmd_input handle from a file descriptor and open the
4188*58e6ee5fSAndroid Build Coastguard Worker  * file. This tests if the file is of trace-cmd format and allocates
4189*58e6ee5fSAndroid Build Coastguard Worker  * a parse event descriptor.
4190*58e6ee5fSAndroid Build Coastguard Worker  *
4191*58e6ee5fSAndroid Build Coastguard Worker  * The returned pointer is not ready to be read yet. A tracecmd_read_headers()
4192*58e6ee5fSAndroid Build Coastguard Worker  * and tracecmd_init_data() still need to be called on the descriptor.
4193*58e6ee5fSAndroid Build Coastguard Worker  *
4194*58e6ee5fSAndroid Build Coastguard Worker  * Unless you know what you are doing with this, you want to use
4195*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_open_fd() instead.
4196*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_alloc_fd(int fd,int flags)4197*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_input *tracecmd_alloc_fd(int fd, int flags)
4198*58e6ee5fSAndroid Build Coastguard Worker {
4199*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_input *handle;
4200*58e6ee5fSAndroid Build Coastguard Worker 	char test[] = TRACECMD_MAGIC;
4201*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int page_size;
4202*58e6ee5fSAndroid Build Coastguard Worker 	size_t offset;
4203*58e6ee5fSAndroid Build Coastguard Worker 	char *version = NULL;
4204*58e6ee5fSAndroid Build Coastguard Worker 	char *zver = NULL;
4205*58e6ee5fSAndroid Build Coastguard Worker 	char *zname = NULL;
4206*58e6ee5fSAndroid Build Coastguard Worker 	char buf[BUFSIZ];
4207*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long ver;
4208*58e6ee5fSAndroid Build Coastguard Worker 
4209*58e6ee5fSAndroid Build Coastguard Worker 	handle = malloc(sizeof(*handle));
4210*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle)
4211*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
4212*58e6ee5fSAndroid Build Coastguard Worker 	memset(handle, 0, sizeof(*handle));
4213*58e6ee5fSAndroid Build Coastguard Worker 
4214*58e6ee5fSAndroid Build Coastguard Worker 	handle->fd = fd;
4215*58e6ee5fSAndroid Build Coastguard Worker 	handle->ref = 1;
4216*58e6ee5fSAndroid Build Coastguard Worker 	handle->latz.fd = -1;
4217*58e6ee5fSAndroid Build Coastguard Worker 	/* By default, use usecs, unless told otherwise */
4218*58e6ee5fSAndroid Build Coastguard Worker 	handle->flags |= TRACECMD_FL_IN_USECS;
4219*58e6ee5fSAndroid Build Coastguard Worker 
4220*58e6ee5fSAndroid Build Coastguard Worker #ifdef INMEMORY_DECOMPRESS
4221*58e6ee5fSAndroid Build Coastguard Worker 	handle->read_zpage = 1;
4222*58e6ee5fSAndroid Build Coastguard Worker #endif
4223*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, buf, 3))
4224*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
4225*58e6ee5fSAndroid Build Coastguard Worker 
4226*58e6ee5fSAndroid Build Coastguard Worker 	if (memcmp(buf, test, 3) != 0)
4227*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
4228*58e6ee5fSAndroid Build Coastguard Worker 
4229*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, buf, 7))
4230*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
4231*58e6ee5fSAndroid Build Coastguard Worker 	if (memcmp(buf, "tracing", 7) != 0)
4232*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
4233*58e6ee5fSAndroid Build Coastguard Worker 
4234*58e6ee5fSAndroid Build Coastguard Worker 	version = read_string(handle);
4235*58e6ee5fSAndroid Build Coastguard Worker 	if (!version)
4236*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
4237*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_info("version = %s", version);
4238*58e6ee5fSAndroid Build Coastguard Worker 	ver = strtol(version, NULL, 10);
4239*58e6ee5fSAndroid Build Coastguard Worker 	if (!ver && errno)
4240*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
4241*58e6ee5fSAndroid Build Coastguard Worker 	if (!tracecmd_is_version_supported(ver)) {
4242*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_warning("Unsupported file version %lu", ver);
4243*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
4244*58e6ee5fSAndroid Build Coastguard Worker 	}
4245*58e6ee5fSAndroid Build Coastguard Worker 	handle->file_version = ver;
4246*58e6ee5fSAndroid Build Coastguard Worker 	free(version);
4247*58e6ee5fSAndroid Build Coastguard Worker 	version = NULL;
4248*58e6ee5fSAndroid Build Coastguard Worker 
4249*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->file_version >= FILE_VERSION_SECTIONS)
4250*58e6ee5fSAndroid Build Coastguard Worker 		handle->flags |= TRACECMD_FL_SECTIONED;
4251*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->file_version >= FILE_VERSION_COMPRESSION)
4252*58e6ee5fSAndroid Build Coastguard Worker 		handle->flags |= TRACECMD_FL_COMPRESSION;
4253*58e6ee5fSAndroid Build Coastguard Worker 
4254*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(handle, buf, 1))
4255*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
4256*58e6ee5fSAndroid Build Coastguard Worker 
4257*58e6ee5fSAndroid Build Coastguard Worker 	handle->pevent = tep_alloc();
4258*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle->pevent)
4259*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
4260*58e6ee5fSAndroid Build Coastguard Worker 
4261*58e6ee5fSAndroid Build Coastguard Worker 	/* register default ftrace functions first */
4262*58e6ee5fSAndroid Build Coastguard Worker 	if (!(flags & TRACECMD_FL_LOAD_NO_PLUGINS) &&
4263*58e6ee5fSAndroid Build Coastguard Worker 	    !(flags & TRACECMD_FL_LOAD_NO_SYSTEM_PLUGINS))
4264*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_ftrace_overrides(handle, &handle->finfo);
4265*58e6ee5fSAndroid Build Coastguard Worker 
4266*58e6ee5fSAndroid Build Coastguard Worker 	handle->plugin_list = trace_load_plugins(handle->pevent, flags);
4267*58e6ee5fSAndroid Build Coastguard Worker 
4268*58e6ee5fSAndroid Build Coastguard Worker 	tep_set_file_bigendian(handle->pevent, buf[0]);
4269*58e6ee5fSAndroid Build Coastguard Worker 	tep_set_local_bigendian(handle->pevent, tracecmd_host_bigendian());
4270*58e6ee5fSAndroid Build Coastguard Worker 
4271*58e6ee5fSAndroid Build Coastguard Worker 	do_read_check(handle, buf, 1);
4272*58e6ee5fSAndroid Build Coastguard Worker 	handle->long_size = buf[0];
4273*58e6ee5fSAndroid Build Coastguard Worker 	tep_set_long_size(handle->pevent, handle->long_size);
4274*58e6ee5fSAndroid Build Coastguard Worker 
4275*58e6ee5fSAndroid Build Coastguard Worker 	read4(handle, &page_size);
4276*58e6ee5fSAndroid Build Coastguard Worker 	handle->page_size = page_size;
4277*58e6ee5fSAndroid Build Coastguard Worker 	handle->next_offset = page_size;
4278*58e6ee5fSAndroid Build Coastguard Worker 
4279*58e6ee5fSAndroid Build Coastguard Worker 	offset = lseek64(handle->fd, 0, SEEK_CUR);
4280*58e6ee5fSAndroid Build Coastguard Worker 	handle->total_file_size = lseek64(handle->fd, 0, SEEK_END);
4281*58e6ee5fSAndroid Build Coastguard Worker 	lseek64(handle->fd, offset, SEEK_SET);
4282*58e6ee5fSAndroid Build Coastguard Worker 
4283*58e6ee5fSAndroid Build Coastguard Worker 	if (HAS_COMPRESSION(handle)) {
4284*58e6ee5fSAndroid Build Coastguard Worker 		zname = read_string(handle);
4285*58e6ee5fSAndroid Build Coastguard Worker 		if (!zname)
4286*58e6ee5fSAndroid Build Coastguard Worker 			goto failed_read;
4287*58e6ee5fSAndroid Build Coastguard Worker 
4288*58e6ee5fSAndroid Build Coastguard Worker 		zver = read_string(handle);
4289*58e6ee5fSAndroid Build Coastguard Worker 		if (!zver)
4290*58e6ee5fSAndroid Build Coastguard Worker 			goto failed_read;
4291*58e6ee5fSAndroid Build Coastguard Worker 
4292*58e6ee5fSAndroid Build Coastguard Worker 		if (strcmp(zname, "none") == 0) {
4293*58e6ee5fSAndroid Build Coastguard Worker 			handle->read_zpage = false;
4294*58e6ee5fSAndroid Build Coastguard Worker 			handle->flags &= ~TRACECMD_FL_COMPRESSION;
4295*58e6ee5fSAndroid Build Coastguard Worker 		} else {
4296*58e6ee5fSAndroid Build Coastguard Worker 			handle->compress = tracecmd_compress_alloc(zname, zver,
4297*58e6ee5fSAndroid Build Coastguard Worker 								   handle->fd,
4298*58e6ee5fSAndroid Build Coastguard Worker 								   handle->pevent, NULL);
4299*58e6ee5fSAndroid Build Coastguard Worker 			if (!handle->compress) {
4300*58e6ee5fSAndroid Build Coastguard Worker 				tracecmd_warning("Unsupported file compression %s %s", zname, zver);
4301*58e6ee5fSAndroid Build Coastguard Worker 				goto failed_read;
4302*58e6ee5fSAndroid Build Coastguard Worker 			}
4303*58e6ee5fSAndroid Build Coastguard Worker 		}
4304*58e6ee5fSAndroid Build Coastguard Worker 
4305*58e6ee5fSAndroid Build Coastguard Worker 		free(zname);
4306*58e6ee5fSAndroid Build Coastguard Worker 		free(zver);
4307*58e6ee5fSAndroid Build Coastguard Worker 	}
4308*58e6ee5fSAndroid Build Coastguard Worker 
4309*58e6ee5fSAndroid Build Coastguard Worker 	if (HAS_SECTIONS(handle)) {
4310*58e6ee5fSAndroid Build Coastguard Worker 		if (read8(handle, &(handle->options_start))) {
4311*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_warning("Filed to read the offset of the first option section");
4312*58e6ee5fSAndroid Build Coastguard Worker 			goto failed_read;
4313*58e6ee5fSAndroid Build Coastguard Worker 		}
4314*58e6ee5fSAndroid Build Coastguard Worker 		read_metadata_strings(handle);
4315*58e6ee5fSAndroid Build Coastguard Worker 	}
4316*58e6ee5fSAndroid Build Coastguard Worker 
4317*58e6ee5fSAndroid Build Coastguard Worker 	handle->file_state = TRACECMD_FILE_INIT;
4318*58e6ee5fSAndroid Build Coastguard Worker 
4319*58e6ee5fSAndroid Build Coastguard Worker 	return handle;
4320*58e6ee5fSAndroid Build Coastguard Worker 
4321*58e6ee5fSAndroid Build Coastguard Worker  failed_read:
4322*58e6ee5fSAndroid Build Coastguard Worker 	free(version);
4323*58e6ee5fSAndroid Build Coastguard Worker 	free(zname);
4324*58e6ee5fSAndroid Build Coastguard Worker 	free(zver);
4325*58e6ee5fSAndroid Build Coastguard Worker 	free(handle);
4326*58e6ee5fSAndroid Build Coastguard Worker 
4327*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
4328*58e6ee5fSAndroid Build Coastguard Worker }
4329*58e6ee5fSAndroid Build Coastguard Worker 
4330*58e6ee5fSAndroid Build Coastguard Worker /**
4331*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_alloc_fd - create a tracecmd_input handle from a file name
4332*58e6ee5fSAndroid Build Coastguard Worker  * @file: the file name of the file that is of tracecmd data type.
4333*58e6ee5fSAndroid Build Coastguard Worker  * @flags: bitmask of enum tracecmd_open_flags
4334*58e6ee5fSAndroid Build Coastguard Worker  *
4335*58e6ee5fSAndroid Build Coastguard Worker  * Allocate a tracecmd_input handle from a given file name and open the
4336*58e6ee5fSAndroid Build Coastguard Worker  * file. This tests if the file is of trace-cmd format and allocates
4337*58e6ee5fSAndroid Build Coastguard Worker  * a parse event descriptor.
4338*58e6ee5fSAndroid Build Coastguard Worker  *
4339*58e6ee5fSAndroid Build Coastguard Worker  * The returned pointer is not ready to be read yet. A tracecmd_read_headers()
4340*58e6ee5fSAndroid Build Coastguard Worker  * and tracecmd_init_data() still need to be called on the descriptor.
4341*58e6ee5fSAndroid Build Coastguard Worker  *
4342*58e6ee5fSAndroid Build Coastguard Worker  * Unless you know what you are doing with this, you want to use
4343*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_open() instead.
4344*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_alloc(const char * file,int flags)4345*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_input *tracecmd_alloc(const char *file, int flags)
4346*58e6ee5fSAndroid Build Coastguard Worker {
4347*58e6ee5fSAndroid Build Coastguard Worker 	int fd;
4348*58e6ee5fSAndroid Build Coastguard Worker 
4349*58e6ee5fSAndroid Build Coastguard Worker 	fd = open(file, O_RDONLY);
4350*58e6ee5fSAndroid Build Coastguard Worker 	if (fd < 0)
4351*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
4352*58e6ee5fSAndroid Build Coastguard Worker 
4353*58e6ee5fSAndroid Build Coastguard Worker 	return tracecmd_alloc_fd(fd, flags);
4354*58e6ee5fSAndroid Build Coastguard Worker }
4355*58e6ee5fSAndroid Build Coastguard Worker 
4356*58e6ee5fSAndroid Build Coastguard Worker /**
4357*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_open_fd - create a tracecmd_handle from the trace.dat file descriptor
4358*58e6ee5fSAndroid Build Coastguard Worker  * @fd: the file descriptor for the trace.dat file
4359*58e6ee5fSAndroid Build Coastguard Worker  * @flags: bitmask of enum tracecmd_open_flags
4360*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_open_fd(int fd,int flags)4361*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_input *tracecmd_open_fd(int fd, int flags)
4362*58e6ee5fSAndroid Build Coastguard Worker {
4363*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_input *handle;
4364*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
4365*58e6ee5fSAndroid Build Coastguard Worker 
4366*58e6ee5fSAndroid Build Coastguard Worker 	handle = tracecmd_alloc_fd(fd, flags);
4367*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle)
4368*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
4369*58e6ee5fSAndroid Build Coastguard Worker 
4370*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_read_headers(handle, 0) < 0)
4371*58e6ee5fSAndroid Build Coastguard Worker 		goto fail;
4372*58e6ee5fSAndroid Build Coastguard Worker 
4373*58e6ee5fSAndroid Build Coastguard Worker 	if ((ret = tracecmd_init_data(handle)) < 0)
4374*58e6ee5fSAndroid Build Coastguard Worker 		goto fail;
4375*58e6ee5fSAndroid Build Coastguard Worker 
4376*58e6ee5fSAndroid Build Coastguard Worker 	return handle;
4377*58e6ee5fSAndroid Build Coastguard Worker 
4378*58e6ee5fSAndroid Build Coastguard Worker fail:
4379*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_close(handle);
4380*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
4381*58e6ee5fSAndroid Build Coastguard Worker }
4382*58e6ee5fSAndroid Build Coastguard Worker 
4383*58e6ee5fSAndroid Build Coastguard Worker /**
4384*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_open - create a tracecmd_handle from a given file
4385*58e6ee5fSAndroid Build Coastguard Worker  * @file: the file name of the file that is of tracecmd data type.
4386*58e6ee5fSAndroid Build Coastguard Worker  * @flags: bitmask of enum tracecmd_open_flags
4387*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_open(const char * file,int flags)4388*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_input *tracecmd_open(const char *file, int flags)
4389*58e6ee5fSAndroid Build Coastguard Worker {
4390*58e6ee5fSAndroid Build Coastguard Worker 	int fd;
4391*58e6ee5fSAndroid Build Coastguard Worker 
4392*58e6ee5fSAndroid Build Coastguard Worker 	fd = open(file, O_RDONLY);
4393*58e6ee5fSAndroid Build Coastguard Worker 	if (fd < 0)
4394*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
4395*58e6ee5fSAndroid Build Coastguard Worker 
4396*58e6ee5fSAndroid Build Coastguard Worker 	return tracecmd_open_fd(fd, flags);
4397*58e6ee5fSAndroid Build Coastguard Worker }
4398*58e6ee5fSAndroid Build Coastguard Worker 
4399*58e6ee5fSAndroid Build Coastguard Worker /**
4400*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_open_head - create a tracecmd_handle from a given file, read
4401*58e6ee5fSAndroid Build Coastguard Worker  *			and parse only the trace headers from the file
4402*58e6ee5fSAndroid Build Coastguard Worker  * @file: the file name of the file that is of tracecmd data type.
4403*58e6ee5fSAndroid Build Coastguard Worker  * @flags: bitmask of enum tracecmd_open_flags
4404*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_open_head(const char * file,int flags)4405*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_input *tracecmd_open_head(const char *file, int flags)
4406*58e6ee5fSAndroid Build Coastguard Worker {
4407*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_input *handle;
4408*58e6ee5fSAndroid Build Coastguard Worker 	int fd;
4409*58e6ee5fSAndroid Build Coastguard Worker 
4410*58e6ee5fSAndroid Build Coastguard Worker 	fd = open(file, O_RDONLY);
4411*58e6ee5fSAndroid Build Coastguard Worker 	if (fd < 0)
4412*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
4413*58e6ee5fSAndroid Build Coastguard Worker 
4414*58e6ee5fSAndroid Build Coastguard Worker 	handle = tracecmd_alloc_fd(fd, flags);
4415*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle)
4416*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
4417*58e6ee5fSAndroid Build Coastguard Worker 
4418*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_read_headers(handle, 0) < 0)
4419*58e6ee5fSAndroid Build Coastguard Worker 		goto fail;
4420*58e6ee5fSAndroid Build Coastguard Worker 
4421*58e6ee5fSAndroid Build Coastguard Worker 	return handle;
4422*58e6ee5fSAndroid Build Coastguard Worker 
4423*58e6ee5fSAndroid Build Coastguard Worker fail:
4424*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_close(handle);
4425*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
4426*58e6ee5fSAndroid Build Coastguard Worker }
4427*58e6ee5fSAndroid Build Coastguard Worker 
4428*58e6ee5fSAndroid Build Coastguard Worker /**
4429*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_ref - add a reference to the handle
4430*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
4431*58e6ee5fSAndroid Build Coastguard Worker  *
4432*58e6ee5fSAndroid Build Coastguard Worker  * Some applications may share a handle between parts of
4433*58e6ee5fSAndroid Build Coastguard Worker  * the application. Let those parts add reference counters
4434*58e6ee5fSAndroid Build Coastguard Worker  * to the handle, and the last one to close it will free it.
4435*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_ref(struct tracecmd_input * handle)4436*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_ref(struct tracecmd_input *handle)
4437*58e6ee5fSAndroid Build Coastguard Worker {
4438*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle)
4439*58e6ee5fSAndroid Build Coastguard Worker 		return;
4440*58e6ee5fSAndroid Build Coastguard Worker 
4441*58e6ee5fSAndroid Build Coastguard Worker 	handle->ref++;
4442*58e6ee5fSAndroid Build Coastguard Worker }
4443*58e6ee5fSAndroid Build Coastguard Worker 
free_buffer(struct input_buffer_instance * buf)4444*58e6ee5fSAndroid Build Coastguard Worker static inline void free_buffer(struct input_buffer_instance *buf)
4445*58e6ee5fSAndroid Build Coastguard Worker {
4446*58e6ee5fSAndroid Build Coastguard Worker 	free(buf->name);
4447*58e6ee5fSAndroid Build Coastguard Worker 	free(buf->clock);
4448*58e6ee5fSAndroid Build Coastguard Worker 	free(buf->cpu_data);
4449*58e6ee5fSAndroid Build Coastguard Worker }
4450*58e6ee5fSAndroid Build Coastguard Worker 
4451*58e6ee5fSAndroid Build Coastguard Worker /**
4452*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_close - close and free the trace.dat handle
4453*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
4454*58e6ee5fSAndroid Build Coastguard Worker  *
4455*58e6ee5fSAndroid Build Coastguard Worker  * Close the file descriptor of the handle and frees
4456*58e6ee5fSAndroid Build Coastguard Worker  * the resources allocated by the handle.
4457*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_close(struct tracecmd_input * handle)4458*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_close(struct tracecmd_input *handle)
4459*58e6ee5fSAndroid Build Coastguard Worker {
4460*58e6ee5fSAndroid Build Coastguard Worker 	struct zchunk_cache *cache;
4461*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *del_sec;
4462*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data *cpu_data;
4463*58e6ee5fSAndroid Build Coastguard Worker 	struct page_map *page_map, *n;
4464*58e6ee5fSAndroid Build Coastguard Worker 	int cpu;
4465*58e6ee5fSAndroid Build Coastguard Worker 	int i;
4466*58e6ee5fSAndroid Build Coastguard Worker 
4467*58e6ee5fSAndroid Build Coastguard Worker 	if (!handle)
4468*58e6ee5fSAndroid Build Coastguard Worker 		return;
4469*58e6ee5fSAndroid Build Coastguard Worker 
4470*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->ref <= 0) {
4471*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_warning("tracecmd: bad ref count on handle");
4472*58e6ee5fSAndroid Build Coastguard Worker 		return;
4473*58e6ee5fSAndroid Build Coastguard Worker 	}
4474*58e6ee5fSAndroid Build Coastguard Worker 
4475*58e6ee5fSAndroid Build Coastguard Worker 	if (--handle->ref)
4476*58e6ee5fSAndroid Build Coastguard Worker 		return;
4477*58e6ee5fSAndroid Build Coastguard Worker 
4478*58e6ee5fSAndroid Build Coastguard Worker 	for (cpu = 0; cpu < handle->cpus; cpu++) {
4479*58e6ee5fSAndroid Build Coastguard Worker 		/* The tracecmd_peek_data may have cached a record */
4480*58e6ee5fSAndroid Build Coastguard Worker 		free_next(handle, cpu);
4481*58e6ee5fSAndroid Build Coastguard Worker 		free_page(handle, cpu);
4482*58e6ee5fSAndroid Build Coastguard Worker 		if (handle->cpu_data) {
4483*58e6ee5fSAndroid Build Coastguard Worker 			cpu_data = &handle->cpu_data[cpu];
4484*58e6ee5fSAndroid Build Coastguard Worker 			if (cpu_data->kbuf) {
4485*58e6ee5fSAndroid Build Coastguard Worker 				kbuffer_free(cpu_data->kbuf);
4486*58e6ee5fSAndroid Build Coastguard Worker 				if (cpu_data->page_map)
4487*58e6ee5fSAndroid Build Coastguard Worker 					free_page_map(cpu_data->page_map);
4488*58e6ee5fSAndroid Build Coastguard Worker 
4489*58e6ee5fSAndroid Build Coastguard Worker 				if (cpu_data->page_cnt)
4490*58e6ee5fSAndroid Build Coastguard Worker 					tracecmd_warning("%d pages still allocated on cpu %d%s",
4491*58e6ee5fSAndroid Build Coastguard Worker 							 cpu_data->page_cnt, cpu,
4492*58e6ee5fSAndroid Build Coastguard Worker 							 show_records(cpu_data->pages,
4493*58e6ee5fSAndroid Build Coastguard Worker 								      cpu_data->nr_pages));
4494*58e6ee5fSAndroid Build Coastguard Worker 				free(cpu_data->pages);
4495*58e6ee5fSAndroid Build Coastguard Worker 			}
4496*58e6ee5fSAndroid Build Coastguard Worker 			if (cpu_data->compress.fd >= 0) {
4497*58e6ee5fSAndroid Build Coastguard Worker 				close(cpu_data->compress.fd);
4498*58e6ee5fSAndroid Build Coastguard Worker 				unlink(cpu_data->compress.file);
4499*58e6ee5fSAndroid Build Coastguard Worker 			}
4500*58e6ee5fSAndroid Build Coastguard Worker 			while (!list_empty(&cpu_data->compress.cache)) {
4501*58e6ee5fSAndroid Build Coastguard Worker 				cache = container_of(cpu_data->compress.cache.next,
4502*58e6ee5fSAndroid Build Coastguard Worker 						     struct zchunk_cache, list);
4503*58e6ee5fSAndroid Build Coastguard Worker 				list_del(&cache->list);
4504*58e6ee5fSAndroid Build Coastguard Worker 				free(cache->map);
4505*58e6ee5fSAndroid Build Coastguard Worker 				free(cache);
4506*58e6ee5fSAndroid Build Coastguard Worker 			}
4507*58e6ee5fSAndroid Build Coastguard Worker 			free(cpu_data->compress.chunks);
4508*58e6ee5fSAndroid Build Coastguard Worker 			list_for_each_entry_safe(page_map, n, &cpu_data->page_maps, list) {
4509*58e6ee5fSAndroid Build Coastguard Worker 				list_del(&page_map->list);
4510*58e6ee5fSAndroid Build Coastguard Worker 				free(page_map);
4511*58e6ee5fSAndroid Build Coastguard Worker 			}
4512*58e6ee5fSAndroid Build Coastguard Worker 		}
4513*58e6ee5fSAndroid Build Coastguard Worker 	}
4514*58e6ee5fSAndroid Build Coastguard Worker 
4515*58e6ee5fSAndroid Build Coastguard Worker 	free(handle->cpustats);
4516*58e6ee5fSAndroid Build Coastguard Worker 	free(handle->cpu_data);
4517*58e6ee5fSAndroid Build Coastguard Worker 	free(handle->uname);
4518*58e6ee5fSAndroid Build Coastguard Worker 	free(handle->trace_clock);
4519*58e6ee5fSAndroid Build Coastguard Worker 	free(handle->strings);
4520*58e6ee5fSAndroid Build Coastguard Worker 	free(handle->version);
4521*58e6ee5fSAndroid Build Coastguard Worker 	close(handle->fd);
4522*58e6ee5fSAndroid Build Coastguard Worker 	free(handle->latz.chunks);
4523*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->latz.fd >= 0) {
4524*58e6ee5fSAndroid Build Coastguard Worker 		close(handle->latz.fd);
4525*58e6ee5fSAndroid Build Coastguard Worker 		unlink(handle->latz.file);
4526*58e6ee5fSAndroid Build Coastguard Worker 	}
4527*58e6ee5fSAndroid Build Coastguard Worker 	while (handle->sections) {
4528*58e6ee5fSAndroid Build Coastguard Worker 		del_sec = handle->sections;
4529*58e6ee5fSAndroid Build Coastguard Worker 		handle->sections = handle->sections->next;
4530*58e6ee5fSAndroid Build Coastguard Worker 		free(del_sec);
4531*58e6ee5fSAndroid Build Coastguard Worker 	}
4532*58e6ee5fSAndroid Build Coastguard Worker 
4533*58e6ee5fSAndroid Build Coastguard Worker 	free_buffer(&handle->top_buffer);
4534*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < handle->nr_buffers; i++)
4535*58e6ee5fSAndroid Build Coastguard Worker 		free_buffer(&handle->buffers[i]);
4536*58e6ee5fSAndroid Build Coastguard Worker 	free(handle->buffers);
4537*58e6ee5fSAndroid Build Coastguard Worker 
4538*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_free_hooks(handle->hooks);
4539*58e6ee5fSAndroid Build Coastguard Worker 	handle->hooks = NULL;
4540*58e6ee5fSAndroid Build Coastguard Worker 
4541*58e6ee5fSAndroid Build Coastguard Worker 	trace_pid_map_free(handle->pid_maps);
4542*58e6ee5fSAndroid Build Coastguard Worker 	handle->pid_maps = NULL;
4543*58e6ee5fSAndroid Build Coastguard Worker 
4544*58e6ee5fSAndroid Build Coastguard Worker 	trace_tsync_offset_free(&handle->host);
4545*58e6ee5fSAndroid Build Coastguard Worker 	trace_guests_free(handle);
4546*58e6ee5fSAndroid Build Coastguard Worker 
4547*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->flags & TRACECMD_FL_BUFFER_INSTANCE)
4548*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_close(handle->parent);
4549*58e6ee5fSAndroid Build Coastguard Worker 	else {
4550*58e6ee5fSAndroid Build Coastguard Worker 		/* Only main handle frees plugins, pevent and compression context */
4551*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_compress_destroy(handle->compress);
4552*58e6ee5fSAndroid Build Coastguard Worker 		tep_unload_plugins(handle->plugin_list, handle->pevent);
4553*58e6ee5fSAndroid Build Coastguard Worker 		tep_free(handle->pevent);
4554*58e6ee5fSAndroid Build Coastguard Worker 	}
4555*58e6ee5fSAndroid Build Coastguard Worker 	free(handle);
4556*58e6ee5fSAndroid Build Coastguard Worker }
4557*58e6ee5fSAndroid Build Coastguard Worker 
read_copy_size8(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle,unsigned long long * size)4558*58e6ee5fSAndroid Build Coastguard Worker static int read_copy_size8(struct tracecmd_input *in_handle,
4559*58e6ee5fSAndroid Build Coastguard Worker 			   struct tracecmd_output *out_handle, unsigned long long *size)
4560*58e6ee5fSAndroid Build Coastguard Worker {
4561*58e6ee5fSAndroid Build Coastguard Worker 	/* read size */
4562*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(in_handle, size, 8))
4563*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4564*58e6ee5fSAndroid Build Coastguard Worker 
4565*58e6ee5fSAndroid Build Coastguard Worker 	if (do_write_check(out_handle, size, 8))
4566*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4567*58e6ee5fSAndroid Build Coastguard Worker 
4568*58e6ee5fSAndroid Build Coastguard Worker 	*size = tep_read_number(in_handle->pevent, size, 8);
4569*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4570*58e6ee5fSAndroid Build Coastguard Worker }
4571*58e6ee5fSAndroid Build Coastguard Worker 
read_copy_size4(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle,unsigned int * size)4572*58e6ee5fSAndroid Build Coastguard Worker static int read_copy_size4(struct tracecmd_input *in_handle, struct tracecmd_output *out_handle,
4573*58e6ee5fSAndroid Build Coastguard Worker 			   unsigned int *size)
4574*58e6ee5fSAndroid Build Coastguard Worker {
4575*58e6ee5fSAndroid Build Coastguard Worker 	/* read size */
4576*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(in_handle, size, 4))
4577*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4578*58e6ee5fSAndroid Build Coastguard Worker 
4579*58e6ee5fSAndroid Build Coastguard Worker 	if (do_write_check(out_handle, size, 4))
4580*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4581*58e6ee5fSAndroid Build Coastguard Worker 
4582*58e6ee5fSAndroid Build Coastguard Worker 	*size = tep_read_number(in_handle->pevent, size, 4);
4583*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4584*58e6ee5fSAndroid Build Coastguard Worker }
4585*58e6ee5fSAndroid Build Coastguard Worker 
read_copy_data(struct tracecmd_input * in_handle,unsigned long long size,struct tracecmd_output * out_handle)4586*58e6ee5fSAndroid Build Coastguard Worker static int read_copy_data(struct tracecmd_input *in_handle,
4587*58e6ee5fSAndroid Build Coastguard Worker 			  unsigned long long size,
4588*58e6ee5fSAndroid Build Coastguard Worker 			  struct tracecmd_output *out_handle)
4589*58e6ee5fSAndroid Build Coastguard Worker {
4590*58e6ee5fSAndroid Build Coastguard Worker 	char *buf;
4591*58e6ee5fSAndroid Build Coastguard Worker 
4592*58e6ee5fSAndroid Build Coastguard Worker 	buf = malloc(size);
4593*58e6ee5fSAndroid Build Coastguard Worker 	if (!buf)
4594*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4595*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(in_handle, buf, size))
4596*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
4597*58e6ee5fSAndroid Build Coastguard Worker 
4598*58e6ee5fSAndroid Build Coastguard Worker 	if (do_write_check(out_handle, buf, size))
4599*58e6ee5fSAndroid Build Coastguard Worker 		goto failed_read;
4600*58e6ee5fSAndroid Build Coastguard Worker 
4601*58e6ee5fSAndroid Build Coastguard Worker 	free(buf);
4602*58e6ee5fSAndroid Build Coastguard Worker 
4603*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4604*58e6ee5fSAndroid Build Coastguard Worker 
4605*58e6ee5fSAndroid Build Coastguard Worker  failed_read:
4606*58e6ee5fSAndroid Build Coastguard Worker 	free(buf);
4607*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
4608*58e6ee5fSAndroid Build Coastguard Worker }
4609*58e6ee5fSAndroid Build Coastguard Worker 
4610*58e6ee5fSAndroid Build Coastguard Worker 
check_in_state(struct tracecmd_input * handle,int new_state)4611*58e6ee5fSAndroid Build Coastguard Worker static bool check_in_state(struct tracecmd_input *handle, int new_state)
4612*58e6ee5fSAndroid Build Coastguard Worker {
4613*58e6ee5fSAndroid Build Coastguard Worker 	return check_file_state(handle->file_version, handle->file_state, new_state);
4614*58e6ee5fSAndroid Build Coastguard Worker }
4615*58e6ee5fSAndroid Build Coastguard Worker 
copy_header_files(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)4616*58e6ee5fSAndroid Build Coastguard Worker static int copy_header_files(struct tracecmd_input *in_handle,
4617*58e6ee5fSAndroid Build Coastguard Worker 			     struct tracecmd_output *out_handle)
4618*58e6ee5fSAndroid Build Coastguard Worker {
4619*58e6ee5fSAndroid Build Coastguard Worker 	bool compress = out_check_compression(out_handle);
4620*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *sec;
4621*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset;
4622*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
4623*58e6ee5fSAndroid Build Coastguard Worker 
4624*58e6ee5fSAndroid Build Coastguard Worker 	if (!check_in_state(in_handle, TRACECMD_FILE_HEADERS) ||
4625*58e6ee5fSAndroid Build Coastguard Worker 	    !check_out_state(out_handle, TRACECMD_FILE_HEADERS))
4626*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4627*58e6ee5fSAndroid Build Coastguard Worker 
4628*58e6ee5fSAndroid Build Coastguard Worker 	sec = section_open(in_handle, TRACECMD_OPTION_HEADER_INFO);
4629*58e6ee5fSAndroid Build Coastguard Worker 	if (!sec)
4630*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4631*58e6ee5fSAndroid Build Coastguard Worker 
4632*58e6ee5fSAndroid Build Coastguard Worker 	offset = out_write_section_header(out_handle, TRACECMD_OPTION_HEADER_INFO,
4633*58e6ee5fSAndroid Build Coastguard Worker 					  "headers", TRACECMD_SEC_FL_COMPRESS, true);
4634*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_start(out_handle, compress);
4635*58e6ee5fSAndroid Build Coastguard Worker 
4636*58e6ee5fSAndroid Build Coastguard Worker 	/* "header_page"  */
4637*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_data(in_handle, 12, out_handle) < 0)
4638*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4639*58e6ee5fSAndroid Build Coastguard Worker 
4640*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_size8(in_handle, out_handle, &size) < 0)
4641*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4642*58e6ee5fSAndroid Build Coastguard Worker 
4643*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_data(in_handle, size, out_handle) < 0)
4644*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4645*58e6ee5fSAndroid Build Coastguard Worker 
4646*58e6ee5fSAndroid Build Coastguard Worker 	/* "header_event"  */
4647*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_data(in_handle, 13, out_handle) < 0)
4648*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4649*58e6ee5fSAndroid Build Coastguard Worker 
4650*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_size8(in_handle, out_handle, &size) < 0)
4651*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4652*58e6ee5fSAndroid Build Coastguard Worker 
4653*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_data(in_handle, size, out_handle) < 0)
4654*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4655*58e6ee5fSAndroid Build Coastguard Worker 
4656*58e6ee5fSAndroid Build Coastguard Worker 	in_handle->file_state = TRACECMD_FILE_HEADERS;
4657*58e6ee5fSAndroid Build Coastguard Worker 	if (out_compression_end(out_handle, compress))
4658*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4659*58e6ee5fSAndroid Build Coastguard Worker 
4660*58e6ee5fSAndroid Build Coastguard Worker 	out_set_file_state(out_handle, in_handle->file_state);
4661*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4662*58e6ee5fSAndroid Build Coastguard Worker 
4663*58e6ee5fSAndroid Build Coastguard Worker 	if (out_update_section_header(out_handle, offset))
4664*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4665*58e6ee5fSAndroid Build Coastguard Worker 
4666*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4667*58e6ee5fSAndroid Build Coastguard Worker error:
4668*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_reset(out_handle, compress);
4669*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4670*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
4671*58e6ee5fSAndroid Build Coastguard Worker }
4672*58e6ee5fSAndroid Build Coastguard Worker 
copy_ftrace_files(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)4673*58e6ee5fSAndroid Build Coastguard Worker static int copy_ftrace_files(struct tracecmd_input *in_handle, struct tracecmd_output *out_handle)
4674*58e6ee5fSAndroid Build Coastguard Worker {
4675*58e6ee5fSAndroid Build Coastguard Worker 	bool compress = out_check_compression(out_handle);
4676*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *sec;
4677*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset;
4678*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
4679*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int count;
4680*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int i;
4681*58e6ee5fSAndroid Build Coastguard Worker 
4682*58e6ee5fSAndroid Build Coastguard Worker 	if (!check_in_state(in_handle, TRACECMD_FILE_FTRACE_EVENTS) ||
4683*58e6ee5fSAndroid Build Coastguard Worker 	    !check_out_state(out_handle, TRACECMD_FILE_FTRACE_EVENTS))
4684*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4685*58e6ee5fSAndroid Build Coastguard Worker 
4686*58e6ee5fSAndroid Build Coastguard Worker 	sec = section_open(in_handle, TRACECMD_OPTION_FTRACE_EVENTS);
4687*58e6ee5fSAndroid Build Coastguard Worker 	if (!sec)
4688*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4689*58e6ee5fSAndroid Build Coastguard Worker 	offset = out_write_section_header(out_handle, TRACECMD_OPTION_FTRACE_EVENTS,
4690*58e6ee5fSAndroid Build Coastguard Worker 					  "ftrace events", TRACECMD_SEC_FL_COMPRESS, true);
4691*58e6ee5fSAndroid Build Coastguard Worker 
4692*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_start(out_handle, compress);
4693*58e6ee5fSAndroid Build Coastguard Worker 
4694*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_size4(in_handle, out_handle, &count) < 0)
4695*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4696*58e6ee5fSAndroid Build Coastguard Worker 
4697*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < count; i++) {
4698*58e6ee5fSAndroid Build Coastguard Worker 
4699*58e6ee5fSAndroid Build Coastguard Worker 		if (read_copy_size8(in_handle, out_handle, &size) < 0)
4700*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
4701*58e6ee5fSAndroid Build Coastguard Worker 
4702*58e6ee5fSAndroid Build Coastguard Worker 		if (read_copy_data(in_handle, size, out_handle) < 0)
4703*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
4704*58e6ee5fSAndroid Build Coastguard Worker 	}
4705*58e6ee5fSAndroid Build Coastguard Worker 
4706*58e6ee5fSAndroid Build Coastguard Worker 	in_handle->file_state = TRACECMD_FILE_FTRACE_EVENTS;
4707*58e6ee5fSAndroid Build Coastguard Worker 	if (out_compression_end(out_handle, compress))
4708*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4709*58e6ee5fSAndroid Build Coastguard Worker 
4710*58e6ee5fSAndroid Build Coastguard Worker 	out_set_file_state(out_handle, in_handle->file_state);
4711*58e6ee5fSAndroid Build Coastguard Worker 
4712*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4713*58e6ee5fSAndroid Build Coastguard Worker 
4714*58e6ee5fSAndroid Build Coastguard Worker 	if (out_update_section_header(out_handle, offset))
4715*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4716*58e6ee5fSAndroid Build Coastguard Worker 
4717*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4718*58e6ee5fSAndroid Build Coastguard Worker error:
4719*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_reset(out_handle, compress);
4720*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4721*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
4722*58e6ee5fSAndroid Build Coastguard Worker }
4723*58e6ee5fSAndroid Build Coastguard Worker 
copy_event_files(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)4724*58e6ee5fSAndroid Build Coastguard Worker static int copy_event_files(struct tracecmd_input *in_handle, struct tracecmd_output *out_handle)
4725*58e6ee5fSAndroid Build Coastguard Worker {
4726*58e6ee5fSAndroid Build Coastguard Worker 	bool compress = out_check_compression(out_handle);
4727*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *sec;
4728*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset;
4729*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
4730*58e6ee5fSAndroid Build Coastguard Worker 	char *system;
4731*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int systems;
4732*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int count;
4733*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int i,x;
4734*58e6ee5fSAndroid Build Coastguard Worker 
4735*58e6ee5fSAndroid Build Coastguard Worker 	if (!check_in_state(in_handle, TRACECMD_FILE_ALL_EVENTS) ||
4736*58e6ee5fSAndroid Build Coastguard Worker 	    !check_out_state(out_handle, TRACECMD_FILE_ALL_EVENTS))
4737*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4738*58e6ee5fSAndroid Build Coastguard Worker 
4739*58e6ee5fSAndroid Build Coastguard Worker 	sec = section_open(in_handle, TRACECMD_OPTION_EVENT_FORMATS);
4740*58e6ee5fSAndroid Build Coastguard Worker 	if (!sec)
4741*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4742*58e6ee5fSAndroid Build Coastguard Worker 	offset = out_write_section_header(out_handle, TRACECMD_OPTION_EVENT_FORMATS,
4743*58e6ee5fSAndroid Build Coastguard Worker 					  "events format", TRACECMD_SEC_FL_COMPRESS, true);
4744*58e6ee5fSAndroid Build Coastguard Worker 
4745*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_start(out_handle, compress);
4746*58e6ee5fSAndroid Build Coastguard Worker 
4747*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_size4(in_handle, out_handle, &systems) < 0)
4748*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4749*58e6ee5fSAndroid Build Coastguard Worker 
4750*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < systems; i++) {
4751*58e6ee5fSAndroid Build Coastguard Worker 		system = read_string(in_handle);
4752*58e6ee5fSAndroid Build Coastguard Worker 		if (!system)
4753*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
4754*58e6ee5fSAndroid Build Coastguard Worker 		if (do_write_check(out_handle, system, strlen(system) + 1)) {
4755*58e6ee5fSAndroid Build Coastguard Worker 			free(system);
4756*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
4757*58e6ee5fSAndroid Build Coastguard Worker 		}
4758*58e6ee5fSAndroid Build Coastguard Worker 		free(system);
4759*58e6ee5fSAndroid Build Coastguard Worker 
4760*58e6ee5fSAndroid Build Coastguard Worker 		if (read_copy_size4(in_handle, out_handle, &count) < 0)
4761*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
4762*58e6ee5fSAndroid Build Coastguard Worker 
4763*58e6ee5fSAndroid Build Coastguard Worker 		for (x=0; x < count; x++) {
4764*58e6ee5fSAndroid Build Coastguard Worker 			if (read_copy_size8(in_handle, out_handle, &size) < 0)
4765*58e6ee5fSAndroid Build Coastguard Worker 				goto error;
4766*58e6ee5fSAndroid Build Coastguard Worker 
4767*58e6ee5fSAndroid Build Coastguard Worker 			if (read_copy_data(in_handle, size, out_handle) < 0)
4768*58e6ee5fSAndroid Build Coastguard Worker 				goto error;
4769*58e6ee5fSAndroid Build Coastguard Worker 		}
4770*58e6ee5fSAndroid Build Coastguard Worker 	}
4771*58e6ee5fSAndroid Build Coastguard Worker 
4772*58e6ee5fSAndroid Build Coastguard Worker 	in_handle->file_state = TRACECMD_FILE_ALL_EVENTS;
4773*58e6ee5fSAndroid Build Coastguard Worker 	if (out_compression_end(out_handle, compress))
4774*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4775*58e6ee5fSAndroid Build Coastguard Worker 
4776*58e6ee5fSAndroid Build Coastguard Worker 	out_set_file_state(out_handle, in_handle->file_state);
4777*58e6ee5fSAndroid Build Coastguard Worker 
4778*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4779*58e6ee5fSAndroid Build Coastguard Worker 
4780*58e6ee5fSAndroid Build Coastguard Worker 	if (out_update_section_header(out_handle, offset))
4781*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4782*58e6ee5fSAndroid Build Coastguard Worker 
4783*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4784*58e6ee5fSAndroid Build Coastguard Worker error:
4785*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_reset(out_handle, compress);
4786*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4787*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
4788*58e6ee5fSAndroid Build Coastguard Worker }
4789*58e6ee5fSAndroid Build Coastguard Worker 
copy_proc_kallsyms(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)4790*58e6ee5fSAndroid Build Coastguard Worker static int copy_proc_kallsyms(struct tracecmd_input *in_handle, struct tracecmd_output *out_handle)
4791*58e6ee5fSAndroid Build Coastguard Worker {
4792*58e6ee5fSAndroid Build Coastguard Worker 	bool compress = out_check_compression(out_handle);
4793*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *sec;
4794*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset;
4795*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int size;
4796*58e6ee5fSAndroid Build Coastguard Worker 
4797*58e6ee5fSAndroid Build Coastguard Worker 	if (!check_in_state(in_handle, TRACECMD_FILE_KALLSYMS) ||
4798*58e6ee5fSAndroid Build Coastguard Worker 	    !check_out_state(out_handle, TRACECMD_FILE_KALLSYMS))
4799*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4800*58e6ee5fSAndroid Build Coastguard Worker 
4801*58e6ee5fSAndroid Build Coastguard Worker 	sec = section_open(in_handle, TRACECMD_OPTION_KALLSYMS);
4802*58e6ee5fSAndroid Build Coastguard Worker 	if (!sec)
4803*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4804*58e6ee5fSAndroid Build Coastguard Worker 	offset = out_write_section_header(out_handle, TRACECMD_OPTION_KALLSYMS,
4805*58e6ee5fSAndroid Build Coastguard Worker 					  "kallsyms", TRACECMD_SEC_FL_COMPRESS, true);
4806*58e6ee5fSAndroid Build Coastguard Worker 
4807*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_start(out_handle, compress);
4808*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_size4(in_handle, out_handle, &size) < 0)
4809*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4810*58e6ee5fSAndroid Build Coastguard Worker 
4811*58e6ee5fSAndroid Build Coastguard Worker 	if (!size)
4812*58e6ee5fSAndroid Build Coastguard Worker 		goto out; /* OK? */
4813*58e6ee5fSAndroid Build Coastguard Worker 
4814*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_data(in_handle, size, out_handle) < 0)
4815*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4816*58e6ee5fSAndroid Build Coastguard Worker out:
4817*58e6ee5fSAndroid Build Coastguard Worker 	in_handle->file_state = TRACECMD_FILE_KALLSYMS;
4818*58e6ee5fSAndroid Build Coastguard Worker 	if (out_compression_end(out_handle, compress))
4819*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4820*58e6ee5fSAndroid Build Coastguard Worker 
4821*58e6ee5fSAndroid Build Coastguard Worker 	out_set_file_state(out_handle, in_handle->file_state);
4822*58e6ee5fSAndroid Build Coastguard Worker 
4823*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4824*58e6ee5fSAndroid Build Coastguard Worker 
4825*58e6ee5fSAndroid Build Coastguard Worker 	if (out_update_section_header(out_handle, offset))
4826*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4827*58e6ee5fSAndroid Build Coastguard Worker 
4828*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4829*58e6ee5fSAndroid Build Coastguard Worker error:
4830*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_reset(out_handle, compress);
4831*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4832*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
4833*58e6ee5fSAndroid Build Coastguard Worker }
4834*58e6ee5fSAndroid Build Coastguard Worker 
copy_ftrace_printk(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)4835*58e6ee5fSAndroid Build Coastguard Worker static int copy_ftrace_printk(struct tracecmd_input *in_handle, struct tracecmd_output *out_handle)
4836*58e6ee5fSAndroid Build Coastguard Worker {
4837*58e6ee5fSAndroid Build Coastguard Worker 	bool compress = out_check_compression(out_handle);
4838*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *sec;
4839*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset;
4840*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int size;
4841*58e6ee5fSAndroid Build Coastguard Worker 
4842*58e6ee5fSAndroid Build Coastguard Worker 	if (!check_in_state(in_handle, TRACECMD_FILE_PRINTK) ||
4843*58e6ee5fSAndroid Build Coastguard Worker 	    !check_out_state(out_handle, TRACECMD_FILE_PRINTK))
4844*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4845*58e6ee5fSAndroid Build Coastguard Worker 
4846*58e6ee5fSAndroid Build Coastguard Worker 	sec = section_open(in_handle, TRACECMD_OPTION_PRINTK);
4847*58e6ee5fSAndroid Build Coastguard Worker 	if (!sec)
4848*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4849*58e6ee5fSAndroid Build Coastguard Worker 
4850*58e6ee5fSAndroid Build Coastguard Worker 	offset = out_write_section_header(out_handle, TRACECMD_OPTION_PRINTK,
4851*58e6ee5fSAndroid Build Coastguard Worker 					  "printk", TRACECMD_SEC_FL_COMPRESS, true);
4852*58e6ee5fSAndroid Build Coastguard Worker 
4853*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_start(out_handle, compress);
4854*58e6ee5fSAndroid Build Coastguard Worker 
4855*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_size4(in_handle, out_handle, &size) < 0)
4856*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4857*58e6ee5fSAndroid Build Coastguard Worker 
4858*58e6ee5fSAndroid Build Coastguard Worker 	if (!size)
4859*58e6ee5fSAndroid Build Coastguard Worker 		goto out; /* OK? */
4860*58e6ee5fSAndroid Build Coastguard Worker 
4861*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_data(in_handle, size, out_handle) < 0)
4862*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4863*58e6ee5fSAndroid Build Coastguard Worker 
4864*58e6ee5fSAndroid Build Coastguard Worker out:
4865*58e6ee5fSAndroid Build Coastguard Worker 	in_handle->file_state = TRACECMD_FILE_PRINTK;
4866*58e6ee5fSAndroid Build Coastguard Worker 	if (out_compression_end(out_handle, compress))
4867*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4868*58e6ee5fSAndroid Build Coastguard Worker 
4869*58e6ee5fSAndroid Build Coastguard Worker 	out_set_file_state(out_handle, in_handle->file_state);
4870*58e6ee5fSAndroid Build Coastguard Worker 
4871*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4872*58e6ee5fSAndroid Build Coastguard Worker 
4873*58e6ee5fSAndroid Build Coastguard Worker 	if (out_update_section_header(out_handle, offset))
4874*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4875*58e6ee5fSAndroid Build Coastguard Worker 
4876*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4877*58e6ee5fSAndroid Build Coastguard Worker error:
4878*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_reset(out_handle, compress);
4879*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4880*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
4881*58e6ee5fSAndroid Build Coastguard Worker }
4882*58e6ee5fSAndroid Build Coastguard Worker 
copy_command_lines(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)4883*58e6ee5fSAndroid Build Coastguard Worker static int copy_command_lines(struct tracecmd_input *in_handle, struct tracecmd_output *out_handle)
4884*58e6ee5fSAndroid Build Coastguard Worker {
4885*58e6ee5fSAndroid Build Coastguard Worker 	bool compress = out_check_compression(out_handle);
4886*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *sec;
4887*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset;
4888*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
4889*58e6ee5fSAndroid Build Coastguard Worker 
4890*58e6ee5fSAndroid Build Coastguard Worker 	if (!check_in_state(in_handle, TRACECMD_FILE_CMD_LINES) ||
4891*58e6ee5fSAndroid Build Coastguard Worker 	    !check_out_state(out_handle, TRACECMD_FILE_CMD_LINES))
4892*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4893*58e6ee5fSAndroid Build Coastguard Worker 
4894*58e6ee5fSAndroid Build Coastguard Worker 	sec = section_open(in_handle, TRACECMD_OPTION_CMDLINES);
4895*58e6ee5fSAndroid Build Coastguard Worker 	if (!sec)
4896*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4897*58e6ee5fSAndroid Build Coastguard Worker 	offset = out_write_section_header(out_handle, TRACECMD_OPTION_CMDLINES,
4898*58e6ee5fSAndroid Build Coastguard Worker 					  "command lines", TRACECMD_SEC_FL_COMPRESS, true);
4899*58e6ee5fSAndroid Build Coastguard Worker 
4900*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_start(out_handle, compress);
4901*58e6ee5fSAndroid Build Coastguard Worker 
4902*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_size8(in_handle, out_handle, &size) < 0)
4903*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4904*58e6ee5fSAndroid Build Coastguard Worker 
4905*58e6ee5fSAndroid Build Coastguard Worker 	if (!size)
4906*58e6ee5fSAndroid Build Coastguard Worker 		goto out; /* OK? */
4907*58e6ee5fSAndroid Build Coastguard Worker 
4908*58e6ee5fSAndroid Build Coastguard Worker 	if (read_copy_data(in_handle, size, out_handle) < 0)
4909*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4910*58e6ee5fSAndroid Build Coastguard Worker 
4911*58e6ee5fSAndroid Build Coastguard Worker out:
4912*58e6ee5fSAndroid Build Coastguard Worker 	in_handle->file_state = TRACECMD_FILE_CMD_LINES;
4913*58e6ee5fSAndroid Build Coastguard Worker 	if (out_compression_end(out_handle, compress))
4914*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4915*58e6ee5fSAndroid Build Coastguard Worker 
4916*58e6ee5fSAndroid Build Coastguard Worker 	out_set_file_state(out_handle, in_handle->file_state);
4917*58e6ee5fSAndroid Build Coastguard Worker 
4918*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4919*58e6ee5fSAndroid Build Coastguard Worker 
4920*58e6ee5fSAndroid Build Coastguard Worker 	if (out_update_section_header(out_handle, offset))
4921*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
4922*58e6ee5fSAndroid Build Coastguard Worker 
4923*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4924*58e6ee5fSAndroid Build Coastguard Worker error:
4925*58e6ee5fSAndroid Build Coastguard Worker 	out_compression_reset(out_handle, compress);
4926*58e6ee5fSAndroid Build Coastguard Worker 	section_close(in_handle, sec);
4927*58e6ee5fSAndroid Build Coastguard Worker 	return -1;
4928*58e6ee5fSAndroid Build Coastguard Worker }
4929*58e6ee5fSAndroid Build Coastguard Worker 
copy_cpu_count(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)4930*58e6ee5fSAndroid Build Coastguard Worker static int copy_cpu_count(struct tracecmd_input *in_handle, struct tracecmd_output *out_handle)
4931*58e6ee5fSAndroid Build Coastguard Worker {
4932*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int cpus;
4933*58e6ee5fSAndroid Build Coastguard Worker 
4934*58e6ee5fSAndroid Build Coastguard Worker 	if (!check_in_state(in_handle, TRACECMD_FILE_CPU_COUNT) ||
4935*58e6ee5fSAndroid Build Coastguard Worker 	    !check_out_state(out_handle, TRACECMD_FILE_CPU_COUNT))
4936*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4937*58e6ee5fSAndroid Build Coastguard Worker 
4938*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(in_handle)) {
4939*58e6ee5fSAndroid Build Coastguard Worker 		if (read4(in_handle, &cpus))
4940*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
4941*58e6ee5fSAndroid Build Coastguard Worker 	} else {
4942*58e6ee5fSAndroid Build Coastguard Worker 		cpus = in_handle->max_cpu;
4943*58e6ee5fSAndroid Build Coastguard Worker 	}
4944*58e6ee5fSAndroid Build Coastguard Worker 
4945*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_get_out_file_version(out_handle) < FILE_VERSION_SECTIONS) {
4946*58e6ee5fSAndroid Build Coastguard Worker 		cpus = tep_read_number(in_handle->pevent, &cpus, 4);
4947*58e6ee5fSAndroid Build Coastguard Worker 		if (do_write_check(out_handle, &cpus, 4))
4948*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
4949*58e6ee5fSAndroid Build Coastguard Worker 	} else {
4950*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_add_option(out_handle, TRACECMD_OPTION_CPUCOUNT, sizeof(int), &cpus);
4951*58e6ee5fSAndroid Build Coastguard Worker 	}
4952*58e6ee5fSAndroid Build Coastguard Worker 
4953*58e6ee5fSAndroid Build Coastguard Worker 	in_handle->file_state = TRACECMD_FILE_CPU_COUNT;
4954*58e6ee5fSAndroid Build Coastguard Worker 	out_set_file_state(out_handle, in_handle->file_state);
4955*58e6ee5fSAndroid Build Coastguard Worker 
4956*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
4957*58e6ee5fSAndroid Build Coastguard Worker }
4958*58e6ee5fSAndroid Build Coastguard Worker 
4959*58e6ee5fSAndroid Build Coastguard Worker /**
4960*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_copy_headers - Copy headers from a tracecmd_input handle to a file descriptor
4961*58e6ee5fSAndroid Build Coastguard Worker  * @in_handle: input handle for the trace.dat file to copy from.
4962*58e6ee5fSAndroid Build Coastguard Worker  * @out_handle: output handle to the trace.dat file to copy to.
4963*58e6ee5fSAndroid Build Coastguard Worker  * @start_state: The file state to start copying from (zero for the beginnig)
4964*58e6ee5fSAndroid Build Coastguard Worker  * @end_state: The file state to stop at (zero for up to cmdlines)
4965*58e6ee5fSAndroid Build Coastguard Worker  *
4966*58e6ee5fSAndroid Build Coastguard Worker  * This is used to copy trace header data of a trace.dat file to a
4967*58e6ee5fSAndroid Build Coastguard Worker  * file descriptor. Using @start_state and @end_state it may be used
4968*58e6ee5fSAndroid Build Coastguard Worker  * multiple times against the input handle.
4969*58e6ee5fSAndroid Build Coastguard Worker  *
4970*58e6ee5fSAndroid Build Coastguard Worker  * NOTE: The input handle is also modified, and ends at the end
4971*58e6ee5fSAndroid Build Coastguard Worker  *       state as well.
4972*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_copy_headers(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle,enum tracecmd_file_states start_state,enum tracecmd_file_states end_state)4973*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_copy_headers(struct tracecmd_input *in_handle,
4974*58e6ee5fSAndroid Build Coastguard Worker 			  struct tracecmd_output *out_handle,
4975*58e6ee5fSAndroid Build Coastguard Worker 			  enum tracecmd_file_states start_state,
4976*58e6ee5fSAndroid Build Coastguard Worker 			  enum tracecmd_file_states end_state)
4977*58e6ee5fSAndroid Build Coastguard Worker {
4978*58e6ee5fSAndroid Build Coastguard Worker 	struct file_section *sec = NULL;
4979*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
4980*58e6ee5fSAndroid Build Coastguard Worker 
4981*58e6ee5fSAndroid Build Coastguard Worker 	if (!start_state)
4982*58e6ee5fSAndroid Build Coastguard Worker 		start_state = TRACECMD_FILE_HEADERS;
4983*58e6ee5fSAndroid Build Coastguard Worker 	if (!end_state)
4984*58e6ee5fSAndroid Build Coastguard Worker 		end_state = TRACECMD_FILE_CMD_LINES;
4985*58e6ee5fSAndroid Build Coastguard Worker 
4986*58e6ee5fSAndroid Build Coastguard Worker 	if (start_state > end_state)
4987*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
4988*58e6ee5fSAndroid Build Coastguard Worker 
4989*58e6ee5fSAndroid Build Coastguard Worker 	if (end_state < TRACECMD_FILE_HEADERS)
4990*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
4991*58e6ee5fSAndroid Build Coastguard Worker 
4992*58e6ee5fSAndroid Build Coastguard Worker 	if (in_handle->file_state >= start_state) {
4993*58e6ee5fSAndroid Build Coastguard Worker 		/* Set the handle to just before the start state */
4994*58e6ee5fSAndroid Build Coastguard Worker 		sec = section_open(in_handle, TRACECMD_OPTION_HEADER_INFO);
4995*58e6ee5fSAndroid Build Coastguard Worker 		if (!sec)
4996*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
4997*58e6ee5fSAndroid Build Coastguard Worker 		/* Now that the file handle has moved, change its state */
4998*58e6ee5fSAndroid Build Coastguard Worker 		in_handle->file_state = TRACECMD_FILE_INIT;
4999*58e6ee5fSAndroid Build Coastguard Worker 	}
5000*58e6ee5fSAndroid Build Coastguard Worker 
5001*58e6ee5fSAndroid Build Coastguard Worker 	/* Try to bring the input up to the start state - 1 */
5002*58e6ee5fSAndroid Build Coastguard Worker 	ret = tracecmd_read_headers(in_handle, start_state - 1);
5003*58e6ee5fSAndroid Build Coastguard Worker 	if (sec)
5004*58e6ee5fSAndroid Build Coastguard Worker 		section_close(in_handle, sec);
5005*58e6ee5fSAndroid Build Coastguard Worker 	if (ret < 0)
5006*58e6ee5fSAndroid Build Coastguard Worker 		goto out;
5007*58e6ee5fSAndroid Build Coastguard Worker 
5008*58e6ee5fSAndroid Build Coastguard Worker 	switch (start_state) {
5009*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_FILE_HEADERS:
5010*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_header_files(in_handle, out_handle);
5011*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
5012*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
5013*58e6ee5fSAndroid Build Coastguard Worker 
5014*58e6ee5fSAndroid Build Coastguard Worker 		/* fallthrough */
5015*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_FILE_FTRACE_EVENTS:
5016*58e6ee5fSAndroid Build Coastguard Worker 		/* handle's state is now updating with the copies */
5017*58e6ee5fSAndroid Build Coastguard Worker 		if (end_state <= in_handle->file_state)
5018*58e6ee5fSAndroid Build Coastguard Worker 			return 0;
5019*58e6ee5fSAndroid Build Coastguard Worker 
5020*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_ftrace_files(in_handle, out_handle);
5021*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
5022*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
5023*58e6ee5fSAndroid Build Coastguard Worker 
5024*58e6ee5fSAndroid Build Coastguard Worker 		/* fallthrough */
5025*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_FILE_ALL_EVENTS:
5026*58e6ee5fSAndroid Build Coastguard Worker 		if (end_state <= in_handle->file_state)
5027*58e6ee5fSAndroid Build Coastguard Worker 			return 0;
5028*58e6ee5fSAndroid Build Coastguard Worker 
5029*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_event_files(in_handle, out_handle);
5030*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
5031*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
5032*58e6ee5fSAndroid Build Coastguard Worker 
5033*58e6ee5fSAndroid Build Coastguard Worker 		/* fallthrough */
5034*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_FILE_KALLSYMS:
5035*58e6ee5fSAndroid Build Coastguard Worker 		if (end_state <= in_handle->file_state)
5036*58e6ee5fSAndroid Build Coastguard Worker 			return 0;
5037*58e6ee5fSAndroid Build Coastguard Worker 
5038*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_proc_kallsyms(in_handle, out_handle);
5039*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
5040*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
5041*58e6ee5fSAndroid Build Coastguard Worker 
5042*58e6ee5fSAndroid Build Coastguard Worker 		/* fallthrough */
5043*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_FILE_PRINTK:
5044*58e6ee5fSAndroid Build Coastguard Worker 		if (end_state <= in_handle->file_state)
5045*58e6ee5fSAndroid Build Coastguard Worker 			return 0;
5046*58e6ee5fSAndroid Build Coastguard Worker 
5047*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_ftrace_printk(in_handle, out_handle);
5048*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
5049*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
5050*58e6ee5fSAndroid Build Coastguard Worker 
5051*58e6ee5fSAndroid Build Coastguard Worker 		/* fallthrough */
5052*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_FILE_CMD_LINES:
5053*58e6ee5fSAndroid Build Coastguard Worker 		if (end_state <= in_handle->file_state)
5054*58e6ee5fSAndroid Build Coastguard Worker 			return 0;
5055*58e6ee5fSAndroid Build Coastguard Worker 
5056*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_command_lines(in_handle, out_handle);
5057*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
5058*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
5059*58e6ee5fSAndroid Build Coastguard Worker 
5060*58e6ee5fSAndroid Build Coastguard Worker 		/* fallthrough */
5061*58e6ee5fSAndroid Build Coastguard Worker 	case TRACECMD_FILE_CPU_COUNT:
5062*58e6ee5fSAndroid Build Coastguard Worker 		if (end_state <= in_handle->file_state)
5063*58e6ee5fSAndroid Build Coastguard Worker 			return 0;
5064*58e6ee5fSAndroid Build Coastguard Worker 
5065*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_cpu_count(in_handle, out_handle);
5066*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
5067*58e6ee5fSAndroid Build Coastguard Worker 			goto out;
5068*58e6ee5fSAndroid Build Coastguard Worker 
5069*58e6ee5fSAndroid Build Coastguard Worker 		/* fallthrough */
5070*58e6ee5fSAndroid Build Coastguard Worker 	default:
5071*58e6ee5fSAndroid Build Coastguard Worker 		break;
5072*58e6ee5fSAndroid Build Coastguard Worker 	}
5073*58e6ee5fSAndroid Build Coastguard Worker 
5074*58e6ee5fSAndroid Build Coastguard Worker  out:
5075*58e6ee5fSAndroid Build Coastguard Worker 	return ret < 0 ? -1 : 0;
5076*58e6ee5fSAndroid Build Coastguard Worker }
5077*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_copy_buffer_descr(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)5078*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_copy_buffer_descr(struct tracecmd_input *in_handle,
5079*58e6ee5fSAndroid Build Coastguard Worker 			       struct tracecmd_output *out_handle)
5080*58e6ee5fSAndroid Build Coastguard Worker {
5081*58e6ee5fSAndroid Build Coastguard Worker 	int i;
5082*58e6ee5fSAndroid Build Coastguard Worker 
5083*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_get_out_file_version(out_handle) >= FILE_VERSION_SECTIONS)
5084*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
5085*58e6ee5fSAndroid Build Coastguard Worker 
5086*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < in_handle->nr_buffers; i++)
5087*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_add_buffer_info(out_handle, in_handle->buffers[i].name, 0);
5088*58e6ee5fSAndroid Build Coastguard Worker 
5089*58e6ee5fSAndroid Build Coastguard Worker 	return tracecmd_write_buffer_info(out_handle);
5090*58e6ee5fSAndroid Build Coastguard Worker }
5091*58e6ee5fSAndroid Build Coastguard Worker 
copy_options_recursive(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)5092*58e6ee5fSAndroid Build Coastguard Worker static int copy_options_recursive(struct tracecmd_input *in_handle,
5093*58e6ee5fSAndroid Build Coastguard Worker 				  struct tracecmd_output *out_handle)
5094*58e6ee5fSAndroid Build Coastguard Worker {
5095*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short id, flags = 0;
5096*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short option, en2;
5097*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long next;
5098*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int size, en4;
5099*58e6ee5fSAndroid Build Coastguard Worker 	bool skip;
5100*58e6ee5fSAndroid Build Coastguard Worker 
5101*58e6ee5fSAndroid Build Coastguard Worker 	for (;;) {
5102*58e6ee5fSAndroid Build Coastguard Worker 		if (do_read_check(in_handle, &option, 2))
5103*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
5104*58e6ee5fSAndroid Build Coastguard Worker 
5105*58e6ee5fSAndroid Build Coastguard Worker 		en2 = tep_read_number(in_handle->pevent, &option, 2);
5106*58e6ee5fSAndroid Build Coastguard Worker 
5107*58e6ee5fSAndroid Build Coastguard Worker 		if (en2 == TRACECMD_OPTION_DONE && !HAS_SECTIONS(in_handle))
5108*58e6ee5fSAndroid Build Coastguard Worker 			return 0;
5109*58e6ee5fSAndroid Build Coastguard Worker 
5110*58e6ee5fSAndroid Build Coastguard Worker 		/* next 4 bytes is the size of the option */
5111*58e6ee5fSAndroid Build Coastguard Worker 		if (do_read_check(in_handle, &size, 4))
5112*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
5113*58e6ee5fSAndroid Build Coastguard Worker 
5114*58e6ee5fSAndroid Build Coastguard Worker 		en4 = tep_read_number(in_handle->pevent, &size, 4);
5115*58e6ee5fSAndroid Build Coastguard Worker 		if (en2 == TRACECMD_OPTION_DONE) {
5116*58e6ee5fSAndroid Build Coastguard Worker 			/* option done v7 */
5117*58e6ee5fSAndroid Build Coastguard Worker 			if (en4 < 8)
5118*58e6ee5fSAndroid Build Coastguard Worker 				return -1;
5119*58e6ee5fSAndroid Build Coastguard Worker 
5120*58e6ee5fSAndroid Build Coastguard Worker 			if (read8(in_handle, &next))
5121*58e6ee5fSAndroid Build Coastguard Worker 				return -1;
5122*58e6ee5fSAndroid Build Coastguard Worker 
5123*58e6ee5fSAndroid Build Coastguard Worker 			if (!next)
5124*58e6ee5fSAndroid Build Coastguard Worker 				break;
5125*58e6ee5fSAndroid Build Coastguard Worker 
5126*58e6ee5fSAndroid Build Coastguard Worker 			if (do_lseek(in_handle, next, SEEK_SET) == (off64_t)-1)
5127*58e6ee5fSAndroid Build Coastguard Worker 				return -1;
5128*58e6ee5fSAndroid Build Coastguard Worker 
5129*58e6ee5fSAndroid Build Coastguard Worker 			if (read_section_header(in_handle, &id, &flags, NULL, NULL))
5130*58e6ee5fSAndroid Build Coastguard Worker 				return -1;
5131*58e6ee5fSAndroid Build Coastguard Worker 
5132*58e6ee5fSAndroid Build Coastguard Worker 			if (id != TRACECMD_OPTION_DONE)
5133*58e6ee5fSAndroid Build Coastguard Worker 				return -1;
5134*58e6ee5fSAndroid Build Coastguard Worker 
5135*58e6ee5fSAndroid Build Coastguard Worker 			if (flags & TRACECMD_SEC_FL_COMPRESS && in_uncompress_block(in_handle))
5136*58e6ee5fSAndroid Build Coastguard Worker 				return -1;
5137*58e6ee5fSAndroid Build Coastguard Worker 
5138*58e6ee5fSAndroid Build Coastguard Worker 			return copy_options_recursive(in_handle, out_handle);
5139*58e6ee5fSAndroid Build Coastguard Worker 		}
5140*58e6ee5fSAndroid Build Coastguard Worker 		/* Do not copy these, as they have file specific offsets */
5141*58e6ee5fSAndroid Build Coastguard Worker 		switch (en2) {
5142*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_BUFFER:
5143*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_BUFFER_TEXT:
5144*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_HEADER_INFO:
5145*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_FTRACE_EVENTS:
5146*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_EVENT_FORMATS:
5147*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_KALLSYMS:
5148*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_PRINTK:
5149*58e6ee5fSAndroid Build Coastguard Worker 		case TRACECMD_OPTION_CMDLINES:
5150*58e6ee5fSAndroid Build Coastguard Worker 			skip = true;
5151*58e6ee5fSAndroid Build Coastguard Worker 			break;
5152*58e6ee5fSAndroid Build Coastguard Worker 		default:
5153*58e6ee5fSAndroid Build Coastguard Worker 			skip = false;
5154*58e6ee5fSAndroid Build Coastguard Worker 			break;
5155*58e6ee5fSAndroid Build Coastguard Worker 		}
5156*58e6ee5fSAndroid Build Coastguard Worker 		if (skip) {
5157*58e6ee5fSAndroid Build Coastguard Worker 			do_lseek(in_handle, en4, SEEK_CUR);
5158*58e6ee5fSAndroid Build Coastguard Worker 			continue;
5159*58e6ee5fSAndroid Build Coastguard Worker 		}
5160*58e6ee5fSAndroid Build Coastguard Worker 		if (do_write_check(out_handle, &option, 2))
5161*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
5162*58e6ee5fSAndroid Build Coastguard Worker 
5163*58e6ee5fSAndroid Build Coastguard Worker 		if (do_write_check(out_handle, &size, 4))
5164*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
5165*58e6ee5fSAndroid Build Coastguard Worker 
5166*58e6ee5fSAndroid Build Coastguard Worker 		if (read_copy_data(in_handle, en4, out_handle))
5167*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
5168*58e6ee5fSAndroid Build Coastguard Worker 	}
5169*58e6ee5fSAndroid Build Coastguard Worker 
5170*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
5171*58e6ee5fSAndroid Build Coastguard Worker }
5172*58e6ee5fSAndroid Build Coastguard Worker 
copy_options(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)5173*58e6ee5fSAndroid Build Coastguard Worker static int copy_options(struct tracecmd_input *in_handle, struct tracecmd_output *out_handle)
5174*58e6ee5fSAndroid Build Coastguard Worker {
5175*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset, start;
5176*58e6ee5fSAndroid Build Coastguard Worker 	unsigned short id, en2, flags = 0;
5177*58e6ee5fSAndroid Build Coastguard Worker 	int tmp;
5178*58e6ee5fSAndroid Build Coastguard Worker 
5179*58e6ee5fSAndroid Build Coastguard Worker 	if (HAS_SECTIONS(in_handle)) {
5180*58e6ee5fSAndroid Build Coastguard Worker 		if (read_section_header(in_handle, &id, &flags, NULL, NULL))
5181*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
5182*58e6ee5fSAndroid Build Coastguard Worker 
5183*58e6ee5fSAndroid Build Coastguard Worker 		if (id != TRACECMD_OPTION_DONE)
5184*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
5185*58e6ee5fSAndroid Build Coastguard Worker 
5186*58e6ee5fSAndroid Build Coastguard Worker 		if (flags & TRACECMD_SEC_FL_COMPRESS && in_uncompress_block(in_handle))
5187*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
5188*58e6ee5fSAndroid Build Coastguard Worker 	}
5189*58e6ee5fSAndroid Build Coastguard Worker 	start = tracecmd_get_out_file_offset(out_handle);
5190*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_get_out_file_version(out_handle) < FILE_VERSION_SECTIONS) {
5191*58e6ee5fSAndroid Build Coastguard Worker 		if (do_write_check(out_handle, "options  ", 10))
5192*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
5193*58e6ee5fSAndroid Build Coastguard Worker 	}
5194*58e6ee5fSAndroid Build Coastguard Worker 
5195*58e6ee5fSAndroid Build Coastguard Worker 	offset = out_write_section_header(out_handle, TRACECMD_OPTION_DONE, "options", 0, false);
5196*58e6ee5fSAndroid Build Coastguard Worker 
5197*58e6ee5fSAndroid Build Coastguard Worker 	if (copy_options_recursive(in_handle, out_handle))
5198*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
5199*58e6ee5fSAndroid Build Coastguard Worker 
5200*58e6ee5fSAndroid Build Coastguard Worker 	id = TRACECMD_OPTION_DONE;
5201*58e6ee5fSAndroid Build Coastguard Worker 	en2 = tep_read_number(in_handle->pevent, &id, 2);
5202*58e6ee5fSAndroid Build Coastguard Worker 	if (do_write_check(out_handle, &en2, 2))
5203*58e6ee5fSAndroid Build Coastguard Worker 		goto error;
5204*58e6ee5fSAndroid Build Coastguard Worker 
5205*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_get_out_file_version(out_handle) < FILE_VERSION_SECTIONS) {
5206*58e6ee5fSAndroid Build Coastguard Worker 		out_save_options_offset(out_handle, start);
5207*58e6ee5fSAndroid Build Coastguard Worker 	} else {
5208*58e6ee5fSAndroid Build Coastguard Worker 		tmp = 8;
5209*58e6ee5fSAndroid Build Coastguard Worker 		if (do_write_check(out_handle, &tmp, 4))
5210*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
5211*58e6ee5fSAndroid Build Coastguard Worker 
5212*58e6ee5fSAndroid Build Coastguard Worker 		out_save_options_offset(out_handle, start);
5213*58e6ee5fSAndroid Build Coastguard Worker 		start = 0;
5214*58e6ee5fSAndroid Build Coastguard Worker 		if (do_write_check(out_handle, &start, 8))
5215*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
5216*58e6ee5fSAndroid Build Coastguard Worker 	}
5217*58e6ee5fSAndroid Build Coastguard Worker 	out_update_section_header(out_handle, offset);
5218*58e6ee5fSAndroid Build Coastguard Worker 	if (flags & TRACECMD_SEC_FL_COMPRESS)
5219*58e6ee5fSAndroid Build Coastguard Worker 		in_uncompress_reset(in_handle);
5220*58e6ee5fSAndroid Build Coastguard Worker 	in_handle->file_state = TRACECMD_FILE_OPTIONS;
5221*58e6ee5fSAndroid Build Coastguard Worker 	out_set_file_state(out_handle, in_handle->file_state);
5222*58e6ee5fSAndroid Build Coastguard Worker 	/* Append local options */
5223*58e6ee5fSAndroid Build Coastguard Worker 	return tracecmd_append_options(out_handle);
5224*58e6ee5fSAndroid Build Coastguard Worker 
5225*58e6ee5fSAndroid Build Coastguard Worker error:
5226*58e6ee5fSAndroid Build Coastguard Worker 	if (flags & TRACECMD_SEC_FL_COMPRESS)
5227*58e6ee5fSAndroid Build Coastguard Worker 		in_uncompress_reset(in_handle);
5228*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
5229*58e6ee5fSAndroid Build Coastguard Worker }
5230*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_copy_options(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)5231*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_copy_options(struct tracecmd_input *in_handle,
5232*58e6ee5fSAndroid Build Coastguard Worker 			  struct tracecmd_output *out_handle)
5233*58e6ee5fSAndroid Build Coastguard Worker {
5234*58e6ee5fSAndroid Build Coastguard Worker 	if (!check_in_state(in_handle, TRACECMD_FILE_OPTIONS) ||
5235*58e6ee5fSAndroid Build Coastguard Worker 	    !check_out_state(out_handle, TRACECMD_FILE_OPTIONS))
5236*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5237*58e6ee5fSAndroid Build Coastguard Worker 
5238*58e6ee5fSAndroid Build Coastguard Worker 	if (!in_handle->options_start)
5239*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
5240*58e6ee5fSAndroid Build Coastguard Worker 
5241*58e6ee5fSAndroid Build Coastguard Worker 	if (lseek64(in_handle->fd, in_handle->options_start, SEEK_SET) == (off64_t)-1)
5242*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5243*58e6ee5fSAndroid Build Coastguard Worker 
5244*58e6ee5fSAndroid Build Coastguard Worker 	if (copy_options(in_handle, out_handle) < 0)
5245*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5246*58e6ee5fSAndroid Build Coastguard Worker 
5247*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
5248*58e6ee5fSAndroid Build Coastguard Worker }
5249*58e6ee5fSAndroid Build Coastguard Worker 
copy_trace_latency(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle,const char * buf_name)5250*58e6ee5fSAndroid Build Coastguard Worker static int copy_trace_latency(struct tracecmd_input *in_handle,
5251*58e6ee5fSAndroid Build Coastguard Worker 			      struct tracecmd_output *out_handle, const char *buf_name)
5252*58e6ee5fSAndroid Build Coastguard Worker {
5253*58e6ee5fSAndroid Build Coastguard Worker 	int page_size = getpagesize();
5254*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long wsize;
5255*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long offset;
5256*58e6ee5fSAndroid Build Coastguard Worker 	int fd;
5257*58e6ee5fSAndroid Build Coastguard Worker 
5258*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_get_out_file_version(out_handle) < FILE_VERSION_SECTIONS &&
5259*58e6ee5fSAndroid Build Coastguard Worker 	    do_write_check(out_handle, "latency  ", 10))
5260*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5261*58e6ee5fSAndroid Build Coastguard Worker 
5262*58e6ee5fSAndroid Build Coastguard Worker 	offset = tracecmd_get_out_file_offset(out_handle);
5263*58e6ee5fSAndroid Build Coastguard Worker 
5264*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_get_out_file_version(out_handle) >= FILE_VERSION_SECTIONS &&
5265*58e6ee5fSAndroid Build Coastguard Worker 	    !out_add_buffer_option(out_handle, buf_name, TRACECMD_OPTION_BUFFER_TEXT,
5266*58e6ee5fSAndroid Build Coastguard Worker 				   offset, 0, NULL, page_size))
5267*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5268*58e6ee5fSAndroid Build Coastguard Worker 
5269*58e6ee5fSAndroid Build Coastguard Worker 	offset = out_write_section_header(out_handle, TRACECMD_OPTION_BUFFER_TEXT,
5270*58e6ee5fSAndroid Build Coastguard Worker 					  "buffer latency", TRACECMD_SEC_FL_COMPRESS, false);
5271*58e6ee5fSAndroid Build Coastguard Worker 
5272*58e6ee5fSAndroid Build Coastguard Worker 	if (in_handle->latz.fd >= 0)
5273*58e6ee5fSAndroid Build Coastguard Worker 		fd = in_handle->latz.fd;
5274*58e6ee5fSAndroid Build Coastguard Worker 	else
5275*58e6ee5fSAndroid Build Coastguard Worker 		fd = in_handle->fd;
5276*58e6ee5fSAndroid Build Coastguard Worker 
5277*58e6ee5fSAndroid Build Coastguard Worker 	if (!out_copy_fd_compress(out_handle, fd, 0, &wsize, page_size))
5278*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5279*58e6ee5fSAndroid Build Coastguard Worker 
5280*58e6ee5fSAndroid Build Coastguard Worker 	if (out_update_section_header(out_handle, offset))
5281*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5282*58e6ee5fSAndroid Build Coastguard Worker 
5283*58e6ee5fSAndroid Build Coastguard Worker 	out_set_file_state(out_handle, TRACECMD_FILE_CPU_LATENCY);
5284*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
5285*58e6ee5fSAndroid Build Coastguard Worker }
5286*58e6ee5fSAndroid Build Coastguard Worker 
copy_trace_flyrecord_data(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle,const char * buff_name)5287*58e6ee5fSAndroid Build Coastguard Worker static int copy_trace_flyrecord_data(struct tracecmd_input *in_handle,
5288*58e6ee5fSAndroid Build Coastguard Worker 				     struct tracecmd_output *out_handle, const char *buff_name)
5289*58e6ee5fSAndroid Build Coastguard Worker {
5290*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_data_source *data;
5291*58e6ee5fSAndroid Build Coastguard Worker 	int total_size = 0;
5292*58e6ee5fSAndroid Build Coastguard Worker 	int cpus;
5293*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
5294*58e6ee5fSAndroid Build Coastguard Worker 	int i, j;
5295*58e6ee5fSAndroid Build Coastguard Worker 
5296*58e6ee5fSAndroid Build Coastguard Worker 	if (tracecmd_get_out_file_version(out_handle) < FILE_VERSION_SECTIONS)
5297*58e6ee5fSAndroid Build Coastguard Worker 		cpus = in_handle->max_cpu;
5298*58e6ee5fSAndroid Build Coastguard Worker 	else
5299*58e6ee5fSAndroid Build Coastguard Worker 		cpus = in_handle->cpus;
5300*58e6ee5fSAndroid Build Coastguard Worker 
5301*58e6ee5fSAndroid Build Coastguard Worker 	data = calloc(cpus, sizeof(struct cpu_data_source));
5302*58e6ee5fSAndroid Build Coastguard Worker 	if (!data)
5303*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5304*58e6ee5fSAndroid Build Coastguard Worker 
5305*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < in_handle->cpus; i++) {
5306*58e6ee5fSAndroid Build Coastguard Worker 		j = in_handle->cpu_data[i].cpu;
5307*58e6ee5fSAndroid Build Coastguard Worker 		data[j].size = in_handle->cpu_data[i].file_size;
5308*58e6ee5fSAndroid Build Coastguard Worker 		total_size += data[j].size;
5309*58e6ee5fSAndroid Build Coastguard Worker 		if (in_handle->cpu_data[i].compress.fd >= 0) {
5310*58e6ee5fSAndroid Build Coastguard Worker 			data[j].fd = in_handle->cpu_data[i].compress.fd;
5311*58e6ee5fSAndroid Build Coastguard Worker 			data[j].offset = 0;
5312*58e6ee5fSAndroid Build Coastguard Worker 		} else {
5313*58e6ee5fSAndroid Build Coastguard Worker 			data[j].fd = in_handle->fd;
5314*58e6ee5fSAndroid Build Coastguard Worker 			data[j].offset = in_handle->cpu_data[i].file_offset;
5315*58e6ee5fSAndroid Build Coastguard Worker 		}
5316*58e6ee5fSAndroid Build Coastguard Worker 	}
5317*58e6ee5fSAndroid Build Coastguard Worker 	if (total_size || tracecmd_get_out_file_version(out_handle) < FILE_VERSION_SECTIONS)
5318*58e6ee5fSAndroid Build Coastguard Worker 		ret = out_write_cpu_data(out_handle, cpus, data, buff_name);
5319*58e6ee5fSAndroid Build Coastguard Worker 	else
5320*58e6ee5fSAndroid Build Coastguard Worker 		ret = 0;
5321*58e6ee5fSAndroid Build Coastguard Worker 	free(data);
5322*58e6ee5fSAndroid Build Coastguard Worker 
5323*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
5324*58e6ee5fSAndroid Build Coastguard Worker }
5325*58e6ee5fSAndroid Build Coastguard Worker 
copy_flyrecord_buffer(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle,int index)5326*58e6ee5fSAndroid Build Coastguard Worker static int copy_flyrecord_buffer(struct tracecmd_input *in_handle,
5327*58e6ee5fSAndroid Build Coastguard Worker 				 struct tracecmd_output *out_handle, int index)
5328*58e6ee5fSAndroid Build Coastguard Worker {
5329*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_input *instance;
5330*58e6ee5fSAndroid Build Coastguard Worker 	const char *name;
5331*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
5332*58e6ee5fSAndroid Build Coastguard Worker 
5333*58e6ee5fSAndroid Build Coastguard Worker 	name = tracecmd_buffer_instance_name(in_handle, index);
5334*58e6ee5fSAndroid Build Coastguard Worker 	if (!name)
5335*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5336*58e6ee5fSAndroid Build Coastguard Worker 
5337*58e6ee5fSAndroid Build Coastguard Worker 	instance = tracecmd_buffer_instance_handle(in_handle, index);
5338*58e6ee5fSAndroid Build Coastguard Worker 	if (!instance)
5339*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5340*58e6ee5fSAndroid Build Coastguard Worker 
5341*58e6ee5fSAndroid Build Coastguard Worker 	if (!tracecmd_get_quiet(out_handle) && *name)
5342*58e6ee5fSAndroid Build Coastguard Worker 		fprintf(stderr, "\nBuffer: %s\n\n", name);
5343*58e6ee5fSAndroid Build Coastguard Worker 
5344*58e6ee5fSAndroid Build Coastguard Worker 	if (in_handle->buffers[index].latency)
5345*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_trace_latency(in_handle, out_handle, name);
5346*58e6ee5fSAndroid Build Coastguard Worker 	else
5347*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_trace_flyrecord_data(instance, out_handle, name);
5348*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_close(instance);
5349*58e6ee5fSAndroid Build Coastguard Worker 
5350*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
5351*58e6ee5fSAndroid Build Coastguard Worker }
5352*58e6ee5fSAndroid Build Coastguard Worker 
copy_trace_data_from_v6(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)5353*58e6ee5fSAndroid Build Coastguard Worker static int copy_trace_data_from_v6(struct tracecmd_input *in_handle,
5354*58e6ee5fSAndroid Build Coastguard Worker 				   struct tracecmd_output *out_handle)
5355*58e6ee5fSAndroid Build Coastguard Worker {
5356*58e6ee5fSAndroid Build Coastguard Worker 	char buf[10];
5357*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
5358*58e6ee5fSAndroid Build Coastguard Worker 	int i;
5359*58e6ee5fSAndroid Build Coastguard Worker 
5360*58e6ee5fSAndroid Build Coastguard Worker 	if (do_read_check(in_handle, buf, 10))
5361*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5362*58e6ee5fSAndroid Build Coastguard Worker 
5363*58e6ee5fSAndroid Build Coastguard Worker 	if (strncmp(buf, "latency", 7) == 0)
5364*58e6ee5fSAndroid Build Coastguard Worker 		in_handle->file_state = TRACECMD_FILE_CPU_LATENCY;
5365*58e6ee5fSAndroid Build Coastguard Worker 	else if (strncmp(buf, "flyrecord", 9) == 0)
5366*58e6ee5fSAndroid Build Coastguard Worker 		in_handle->file_state = TRACECMD_FILE_CPU_FLYRECORD;
5367*58e6ee5fSAndroid Build Coastguard Worker 
5368*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_init_data(in_handle);
5369*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_set_out_clock(out_handle, in_handle->trace_clock);
5370*58e6ee5fSAndroid Build Coastguard Worker 
5371*58e6ee5fSAndroid Build Coastguard Worker 	if (in_handle->file_state == TRACECMD_FILE_CPU_LATENCY)
5372*58e6ee5fSAndroid Build Coastguard Worker 		return copy_trace_latency(in_handle, out_handle, "");
5373*58e6ee5fSAndroid Build Coastguard Worker 
5374*58e6ee5fSAndroid Build Coastguard Worker 	/* top instance */
5375*58e6ee5fSAndroid Build Coastguard Worker 	ret = copy_trace_flyrecord_data(in_handle, out_handle, "");
5376*58e6ee5fSAndroid Build Coastguard Worker 	if (ret)
5377*58e6ee5fSAndroid Build Coastguard Worker 		return ret;
5378*58e6ee5fSAndroid Build Coastguard Worker 
5379*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < in_handle->nr_buffers; i++)
5380*58e6ee5fSAndroid Build Coastguard Worker 		copy_flyrecord_buffer(in_handle, out_handle, i);
5381*58e6ee5fSAndroid Build Coastguard Worker 
5382*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
5383*58e6ee5fSAndroid Build Coastguard Worker }
5384*58e6ee5fSAndroid Build Coastguard Worker 
copy_trace_data_from_v7(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)5385*58e6ee5fSAndroid Build Coastguard Worker static int copy_trace_data_from_v7(struct tracecmd_input *in_handle,
5386*58e6ee5fSAndroid Build Coastguard Worker 				   struct tracecmd_output *out_handle)
5387*58e6ee5fSAndroid Build Coastguard Worker {
5388*58e6ee5fSAndroid Build Coastguard Worker 	int ret = 0;
5389*58e6ee5fSAndroid Build Coastguard Worker 	int i;
5390*58e6ee5fSAndroid Build Coastguard Worker 
5391*58e6ee5fSAndroid Build Coastguard Worker 	/* Force using temporary files for trace data decompression */
5392*58e6ee5fSAndroid Build Coastguard Worker 	in_handle->read_zpage = false;
5393*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_init_data(in_handle);
5394*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_set_out_clock(out_handle, in_handle->trace_clock);
5395*58e6ee5fSAndroid Build Coastguard Worker 
5396*58e6ee5fSAndroid Build Coastguard Worker 	/* copy top buffer */
5397*58e6ee5fSAndroid Build Coastguard Worker 	if (in_handle->top_buffer.latency)
5398*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_trace_latency(in_handle, out_handle, in_handle->top_buffer.name);
5399*58e6ee5fSAndroid Build Coastguard Worker 	else if (in_handle->top_buffer.cpus)
5400*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_trace_flyrecord_data(in_handle, out_handle,
5401*58e6ee5fSAndroid Build Coastguard Worker 						in_handle->top_buffer.name);
5402*58e6ee5fSAndroid Build Coastguard Worker 	else if (tracecmd_get_out_file_version(out_handle) < FILE_VERSION_SECTIONS)
5403*58e6ee5fSAndroid Build Coastguard Worker 		ret = out_write_emty_cpu_data(out_handle, in_handle->max_cpu);
5404*58e6ee5fSAndroid Build Coastguard Worker 	if (ret)
5405*58e6ee5fSAndroid Build Coastguard Worker 		return ret;
5406*58e6ee5fSAndroid Build Coastguard Worker 
5407*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < in_handle->nr_buffers; i++)
5408*58e6ee5fSAndroid Build Coastguard Worker 		copy_flyrecord_buffer(in_handle, out_handle, i);
5409*58e6ee5fSAndroid Build Coastguard Worker 
5410*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
5411*58e6ee5fSAndroid Build Coastguard Worker }
5412*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_copy_trace_data(struct tracecmd_input * in_handle,struct tracecmd_output * out_handle)5413*58e6ee5fSAndroid Build Coastguard Worker __hidden int tracecmd_copy_trace_data(struct tracecmd_input *in_handle,
5414*58e6ee5fSAndroid Build Coastguard Worker 				      struct tracecmd_output *out_handle)
5415*58e6ee5fSAndroid Build Coastguard Worker {
5416*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
5417*58e6ee5fSAndroid Build Coastguard Worker 
5418*58e6ee5fSAndroid Build Coastguard Worker 	if (!check_in_state(in_handle, TRACECMD_FILE_CPU_FLYRECORD) ||
5419*58e6ee5fSAndroid Build Coastguard Worker 	    !check_out_state(out_handle, TRACECMD_FILE_CPU_FLYRECORD))
5420*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5421*58e6ee5fSAndroid Build Coastguard Worker 
5422*58e6ee5fSAndroid Build Coastguard Worker 	if (in_handle->file_version < FILE_VERSION_SECTIONS)
5423*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_trace_data_from_v6(in_handle, out_handle);
5424*58e6ee5fSAndroid Build Coastguard Worker 	else
5425*58e6ee5fSAndroid Build Coastguard Worker 		ret = copy_trace_data_from_v7(in_handle, out_handle);
5426*58e6ee5fSAndroid Build Coastguard Worker 
5427*58e6ee5fSAndroid Build Coastguard Worker 	return ret;
5428*58e6ee5fSAndroid Build Coastguard Worker }
5429*58e6ee5fSAndroid Build Coastguard Worker 
5430*58e6ee5fSAndroid Build Coastguard Worker /**
5431*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_record_at_buffer_start - return true if record is first on subbuffer
5432*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5433*58e6ee5fSAndroid Build Coastguard Worker  * @record: The record to test if it is the first record on page
5434*58e6ee5fSAndroid Build Coastguard Worker  *
5435*58e6ee5fSAndroid Build Coastguard Worker  * Returns true if the record is the first record on the page.
5436*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_record_at_buffer_start(struct tracecmd_input * handle,struct tep_record * record)5437*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_record_at_buffer_start(struct tracecmd_input *handle,
5438*58e6ee5fSAndroid Build Coastguard Worker 				    struct tep_record *record)
5439*58e6ee5fSAndroid Build Coastguard Worker {
5440*58e6ee5fSAndroid Build Coastguard Worker 	struct page *page = record->priv;
5441*58e6ee5fSAndroid Build Coastguard Worker 	struct kbuffer *kbuf = handle->cpu_data[record->cpu].kbuf;
5442*58e6ee5fSAndroid Build Coastguard Worker 	int offset;
5443*58e6ee5fSAndroid Build Coastguard Worker 
5444*58e6ee5fSAndroid Build Coastguard Worker 	if (!page || !kbuf)
5445*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
5446*58e6ee5fSAndroid Build Coastguard Worker 
5447*58e6ee5fSAndroid Build Coastguard Worker 	offset = record->offset - page->offset;
5448*58e6ee5fSAndroid Build Coastguard Worker 	return offset == kbuffer_start_of_data(kbuf);
5449*58e6ee5fSAndroid Build Coastguard Worker }
5450*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_page_ts(struct tracecmd_input * handle,struct tep_record * record)5451*58e6ee5fSAndroid Build Coastguard Worker unsigned long long tracecmd_page_ts(struct tracecmd_input *handle,
5452*58e6ee5fSAndroid Build Coastguard Worker 				    struct tep_record *record)
5453*58e6ee5fSAndroid Build Coastguard Worker {
5454*58e6ee5fSAndroid Build Coastguard Worker 	struct page *page = record->priv;
5455*58e6ee5fSAndroid Build Coastguard Worker 	struct kbuffer *kbuf = handle->cpu_data[record->cpu].kbuf;
5456*58e6ee5fSAndroid Build Coastguard Worker 
5457*58e6ee5fSAndroid Build Coastguard Worker 	if (!page || !kbuf)
5458*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
5459*58e6ee5fSAndroid Build Coastguard Worker 
5460*58e6ee5fSAndroid Build Coastguard Worker 	return kbuffer_subbuf_timestamp(kbuf, page->map);
5461*58e6ee5fSAndroid Build Coastguard Worker }
5462*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_record_ts_delta(struct tracecmd_input * handle,struct tep_record * record)5463*58e6ee5fSAndroid Build Coastguard Worker unsigned int tracecmd_record_ts_delta(struct tracecmd_input *handle,
5464*58e6ee5fSAndroid Build Coastguard Worker 				      struct tep_record *record)
5465*58e6ee5fSAndroid Build Coastguard Worker {
5466*58e6ee5fSAndroid Build Coastguard Worker 	struct kbuffer *kbuf = handle->cpu_data[record->cpu].kbuf;
5467*58e6ee5fSAndroid Build Coastguard Worker 	struct page *page = record->priv;
5468*58e6ee5fSAndroid Build Coastguard Worker 	int offset;
5469*58e6ee5fSAndroid Build Coastguard Worker 
5470*58e6ee5fSAndroid Build Coastguard Worker 	if (!page || !kbuf)
5471*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
5472*58e6ee5fSAndroid Build Coastguard Worker 
5473*58e6ee5fSAndroid Build Coastguard Worker 	offset = record->offset - page->offset;
5474*58e6ee5fSAndroid Build Coastguard Worker 
5475*58e6ee5fSAndroid Build Coastguard Worker 	return kbuffer_ptr_delta(kbuf, page->map + offset);
5476*58e6ee5fSAndroid Build Coastguard Worker }
5477*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_record_kbuf(struct tracecmd_input * handle,struct tep_record * record)5478*58e6ee5fSAndroid Build Coastguard Worker struct kbuffer *tracecmd_record_kbuf(struct tracecmd_input *handle,
5479*58e6ee5fSAndroid Build Coastguard Worker 				     struct tep_record *record)
5480*58e6ee5fSAndroid Build Coastguard Worker {
5481*58e6ee5fSAndroid Build Coastguard Worker 	return handle->cpu_data[record->cpu].kbuf;
5482*58e6ee5fSAndroid Build Coastguard Worker }
5483*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_record_page(struct tracecmd_input * handle,struct tep_record * record)5484*58e6ee5fSAndroid Build Coastguard Worker void *tracecmd_record_page(struct tracecmd_input *handle,
5485*58e6ee5fSAndroid Build Coastguard Worker 			   struct tep_record *record)
5486*58e6ee5fSAndroid Build Coastguard Worker {
5487*58e6ee5fSAndroid Build Coastguard Worker 	struct page *page = record->priv;
5488*58e6ee5fSAndroid Build Coastguard Worker 
5489*58e6ee5fSAndroid Build Coastguard Worker 	return page ? page->map : NULL;
5490*58e6ee5fSAndroid Build Coastguard Worker }
5491*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_record_offset(struct tracecmd_input * handle,struct tep_record * record)5492*58e6ee5fSAndroid Build Coastguard Worker void *tracecmd_record_offset(struct tracecmd_input *handle,
5493*58e6ee5fSAndroid Build Coastguard Worker 			     struct tep_record *record)
5494*58e6ee5fSAndroid Build Coastguard Worker {
5495*58e6ee5fSAndroid Build Coastguard Worker 	struct page *page = record->priv;
5496*58e6ee5fSAndroid Build Coastguard Worker 	int offset;
5497*58e6ee5fSAndroid Build Coastguard Worker 
5498*58e6ee5fSAndroid Build Coastguard Worker 	if (!page)
5499*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
5500*58e6ee5fSAndroid Build Coastguard Worker 
5501*58e6ee5fSAndroid Build Coastguard Worker 	offset = record->offset - page->offset;
5502*58e6ee5fSAndroid Build Coastguard Worker 
5503*58e6ee5fSAndroid Build Coastguard Worker 	return page->map + offset;
5504*58e6ee5fSAndroid Build Coastguard Worker }
5505*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_buffer_instances(struct tracecmd_input * handle)5506*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_buffer_instances(struct tracecmd_input *handle)
5507*58e6ee5fSAndroid Build Coastguard Worker {
5508*58e6ee5fSAndroid Build Coastguard Worker 	return handle->nr_buffers;
5509*58e6ee5fSAndroid Build Coastguard Worker }
5510*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_buffer_instance_name(struct tracecmd_input * handle,int indx)5511*58e6ee5fSAndroid Build Coastguard Worker const char *tracecmd_buffer_instance_name(struct tracecmd_input *handle, int indx)
5512*58e6ee5fSAndroid Build Coastguard Worker {
5513*58e6ee5fSAndroid Build Coastguard Worker 	if (indx >= handle->nr_buffers)
5514*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
5515*58e6ee5fSAndroid Build Coastguard Worker 
5516*58e6ee5fSAndroid Build Coastguard Worker 	return handle->buffers[indx].name;
5517*58e6ee5fSAndroid Build Coastguard Worker }
5518*58e6ee5fSAndroid Build Coastguard Worker 
5519*58e6ee5fSAndroid Build Coastguard Worker struct tracecmd_input *
tracecmd_buffer_instance_handle(struct tracecmd_input * handle,int indx)5520*58e6ee5fSAndroid Build Coastguard Worker tracecmd_buffer_instance_handle(struct tracecmd_input *handle, int indx)
5521*58e6ee5fSAndroid Build Coastguard Worker {
5522*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_input *new_handle;
5523*58e6ee5fSAndroid Build Coastguard Worker 	struct input_buffer_instance *buffer = &handle->buffers[indx];
5524*58e6ee5fSAndroid Build Coastguard Worker 	size_t offset;
5525*58e6ee5fSAndroid Build Coastguard Worker 	ssize_t ret;
5526*58e6ee5fSAndroid Build Coastguard Worker 
5527*58e6ee5fSAndroid Build Coastguard Worker 	if (indx >= handle->nr_buffers)
5528*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
5529*58e6ee5fSAndroid Build Coastguard Worker 
5530*58e6ee5fSAndroid Build Coastguard Worker 	/*
5531*58e6ee5fSAndroid Build Coastguard Worker 	 * We make a copy of the current handle, but we substitute
5532*58e6ee5fSAndroid Build Coastguard Worker 	 * the cpu data with the cpu data for this buffer.
5533*58e6ee5fSAndroid Build Coastguard Worker 	 */
5534*58e6ee5fSAndroid Build Coastguard Worker 	new_handle = malloc(sizeof(*handle));
5535*58e6ee5fSAndroid Build Coastguard Worker 	if (!new_handle)
5536*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
5537*58e6ee5fSAndroid Build Coastguard Worker 
5538*58e6ee5fSAndroid Build Coastguard Worker 	*new_handle = *handle;
5539*58e6ee5fSAndroid Build Coastguard Worker 	memset(&new_handle->top_buffer, 0, sizeof(new_handle->top_buffer));
5540*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->cpu_data = NULL;
5541*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->nr_buffers = 0;
5542*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->buffers = NULL;
5543*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->version = NULL;
5544*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->sections = NULL;
5545*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->strings = NULL;
5546*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->guest = NULL;
5547*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->ref = 1;
5548*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->trace_clock) {
5549*58e6ee5fSAndroid Build Coastguard Worker 		new_handle->trace_clock = strdup(handle->trace_clock);
5550*58e6ee5fSAndroid Build Coastguard Worker 		if (!new_handle->trace_clock) {
5551*58e6ee5fSAndroid Build Coastguard Worker 			free(new_handle);
5552*58e6ee5fSAndroid Build Coastguard Worker 			return NULL;
5553*58e6ee5fSAndroid Build Coastguard Worker 		}
5554*58e6ee5fSAndroid Build Coastguard Worker 	}
5555*58e6ee5fSAndroid Build Coastguard Worker 	memset(&new_handle->host, 0, sizeof(new_handle->host));
5556*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->parent = handle;
5557*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->cpustats = NULL;
5558*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->hooks = NULL;
5559*58e6ee5fSAndroid Build Coastguard Worker 	if (handle->uname)
5560*58e6ee5fSAndroid Build Coastguard Worker 		/* Ignore if fails to malloc, no biggy */
5561*58e6ee5fSAndroid Build Coastguard Worker 		new_handle->uname = strdup(handle->uname);
5562*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_ref(handle);
5563*58e6ee5fSAndroid Build Coastguard Worker 
5564*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->fd = dup(handle->fd);
5565*58e6ee5fSAndroid Build Coastguard Worker 
5566*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->flags |= TRACECMD_FL_BUFFER_INSTANCE;
5567*58e6ee5fSAndroid Build Coastguard Worker 
5568*58e6ee5fSAndroid Build Coastguard Worker 	new_handle->pid_maps = NULL;
5569*58e6ee5fSAndroid Build Coastguard Worker 	if (!HAS_SECTIONS(handle)) {
5570*58e6ee5fSAndroid Build Coastguard Worker 		/* Save where we currently are */
5571*58e6ee5fSAndroid Build Coastguard Worker 		offset = lseek64(handle->fd, 0, SEEK_CUR);
5572*58e6ee5fSAndroid Build Coastguard Worker 
5573*58e6ee5fSAndroid Build Coastguard Worker 		ret = lseek64(handle->fd, buffer->offset, SEEK_SET);
5574*58e6ee5fSAndroid Build Coastguard Worker 		if (ret == (off64_t)-1) {
5575*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_warning("could not seek to buffer %s offset %ld",
5576*58e6ee5fSAndroid Build Coastguard Worker 					  buffer->name, buffer->offset);
5577*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
5578*58e6ee5fSAndroid Build Coastguard Worker 		}
5579*58e6ee5fSAndroid Build Coastguard Worker 		/*
5580*58e6ee5fSAndroid Build Coastguard Worker 		 * read_options_type() is called right after the CPU count so update
5581*58e6ee5fSAndroid Build Coastguard Worker 		 * file state accordingly.
5582*58e6ee5fSAndroid Build Coastguard Worker 		 */
5583*58e6ee5fSAndroid Build Coastguard Worker 		new_handle->file_state = TRACECMD_FILE_CPU_COUNT;
5584*58e6ee5fSAndroid Build Coastguard Worker 		ret = read_options_type(new_handle);
5585*58e6ee5fSAndroid Build Coastguard Worker 		if (!ret)
5586*58e6ee5fSAndroid Build Coastguard Worker 			ret = read_cpu_data(new_handle);
5587*58e6ee5fSAndroid Build Coastguard Worker 
5588*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0) {
5589*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_warning("failed to read sub buffer %s", buffer->name);
5590*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
5591*58e6ee5fSAndroid Build Coastguard Worker 		}
5592*58e6ee5fSAndroid Build Coastguard Worker 		ret = lseek64(handle->fd, offset, SEEK_SET);
5593*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0) {
5594*58e6ee5fSAndroid Build Coastguard Worker 			tracecmd_warning("could not seek to back to offset %ld", offset);
5595*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
5596*58e6ee5fSAndroid Build Coastguard Worker 		}
5597*58e6ee5fSAndroid Build Coastguard Worker 	} else {
5598*58e6ee5fSAndroid Build Coastguard Worker 		new_handle->page_size = handle->buffers[indx].page_size;
5599*58e6ee5fSAndroid Build Coastguard Worker 		if (init_buffer_cpu_data(new_handle, buffer) < 0)
5600*58e6ee5fSAndroid Build Coastguard Worker 			goto error;
5601*58e6ee5fSAndroid Build Coastguard Worker 	}
5602*58e6ee5fSAndroid Build Coastguard Worker 
5603*58e6ee5fSAndroid Build Coastguard Worker 	return new_handle;
5604*58e6ee5fSAndroid Build Coastguard Worker 
5605*58e6ee5fSAndroid Build Coastguard Worker error:
5606*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_close(new_handle);
5607*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
5608*58e6ee5fSAndroid Build Coastguard Worker }
5609*58e6ee5fSAndroid Build Coastguard Worker 
tracecmd_is_buffer_instance(struct tracecmd_input * handle)5610*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_is_buffer_instance(struct tracecmd_input *handle)
5611*58e6ee5fSAndroid Build Coastguard Worker {
5612*58e6ee5fSAndroid Build Coastguard Worker 	return handle->flags & TRACECMD_FL_BUFFER_INSTANCE;
5613*58e6ee5fSAndroid Build Coastguard Worker }
5614*58e6ee5fSAndroid Build Coastguard Worker 
5615*58e6ee5fSAndroid Build Coastguard Worker /**
5616*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_long_size - return the size of "long" for the arch
5617*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5618*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_long_size(struct tracecmd_input * handle)5619*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_long_size(struct tracecmd_input *handle)
5620*58e6ee5fSAndroid Build Coastguard Worker {
5621*58e6ee5fSAndroid Build Coastguard Worker 	return handle->long_size;
5622*58e6ee5fSAndroid Build Coastguard Worker }
5623*58e6ee5fSAndroid Build Coastguard Worker 
5624*58e6ee5fSAndroid Build Coastguard Worker /**
5625*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_page_size - return the PAGE_SIZE for the arch
5626*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5627*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_page_size(struct tracecmd_input * handle)5628*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_page_size(struct tracecmd_input *handle)
5629*58e6ee5fSAndroid Build Coastguard Worker {
5630*58e6ee5fSAndroid Build Coastguard Worker 	return handle->page_size;
5631*58e6ee5fSAndroid Build Coastguard Worker }
5632*58e6ee5fSAndroid Build Coastguard Worker 
5633*58e6ee5fSAndroid Build Coastguard Worker /**
5634*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_page_size - return the number of CPUs recorded
5635*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5636*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_cpus(struct tracecmd_input * handle)5637*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_cpus(struct tracecmd_input *handle)
5638*58e6ee5fSAndroid Build Coastguard Worker {
5639*58e6ee5fSAndroid Build Coastguard Worker 	return handle->max_cpu;
5640*58e6ee5fSAndroid Build Coastguard Worker }
5641*58e6ee5fSAndroid Build Coastguard Worker 
5642*58e6ee5fSAndroid Build Coastguard Worker /**
5643*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_tep - return the tep handle
5644*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5645*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_tep(struct tracecmd_input * handle)5646*58e6ee5fSAndroid Build Coastguard Worker struct tep_handle *tracecmd_get_tep(struct tracecmd_input *handle)
5647*58e6ee5fSAndroid Build Coastguard Worker {
5648*58e6ee5fSAndroid Build Coastguard Worker 	return handle->pevent;
5649*58e6ee5fSAndroid Build Coastguard Worker }
5650*58e6ee5fSAndroid Build Coastguard Worker 
5651*58e6ee5fSAndroid Build Coastguard Worker /**
5652*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_in_file_version - return the trace.dat file version
5653*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5654*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_in_file_version(struct tracecmd_input * handle)5655*58e6ee5fSAndroid Build Coastguard Worker unsigned long tracecmd_get_in_file_version(struct tracecmd_input *handle)
5656*58e6ee5fSAndroid Build Coastguard Worker {
5657*58e6ee5fSAndroid Build Coastguard Worker 	return handle->file_version;
5658*58e6ee5fSAndroid Build Coastguard Worker }
5659*58e6ee5fSAndroid Build Coastguard Worker 
5660*58e6ee5fSAndroid Build Coastguard Worker /**
5661*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_file_compress_proto - get name and version of compression algorithm
5662*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5663*58e6ee5fSAndroid Build Coastguard Worker  * @name: return, name of the compression algorithm.
5664*58e6ee5fSAndroid Build Coastguard Worker  * @version: return, version of the compression algorithm.
5665*58e6ee5fSAndroid Build Coastguard Worker  *
5666*58e6ee5fSAndroid Build Coastguard Worker  * Get the name and the version of the compression algorithm, used to
5667*58e6ee5fSAndroid Build Coastguard Worker  * compress the file associated with @handle.
5668*58e6ee5fSAndroid Build Coastguard Worker  * Returns 0 on success, or -1 in case of an error. If 0 is returned,
5669*58e6ee5fSAndroid Build Coastguard Worker  * the name and version of the algorithm are stored in @name and @version.
5670*58e6ee5fSAndroid Build Coastguard Worker  * The returned strings must *not* be freed.
5671*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_file_compress_proto(struct tracecmd_input * handle,const char ** name,const char ** version)5672*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_get_file_compress_proto(struct tracecmd_input *handle,
5673*58e6ee5fSAndroid Build Coastguard Worker 				     const char **name, const char **version)
5674*58e6ee5fSAndroid Build Coastguard Worker {
5675*58e6ee5fSAndroid Build Coastguard Worker 	return tracecmd_compress_proto_get_name(handle->compress, name, version);
5676*58e6ee5fSAndroid Build Coastguard Worker }
5677*58e6ee5fSAndroid Build Coastguard Worker 
5678*58e6ee5fSAndroid Build Coastguard Worker /**
5679*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_use_trace_clock - return use_trace_clock
5680*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5681*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_use_trace_clock(struct tracecmd_input * handle)5682*58e6ee5fSAndroid Build Coastguard Worker bool tracecmd_get_use_trace_clock(struct tracecmd_input *handle)
5683*58e6ee5fSAndroid Build Coastguard Worker {
5684*58e6ee5fSAndroid Build Coastguard Worker 	return handle->use_trace_clock;
5685*58e6ee5fSAndroid Build Coastguard Worker }
5686*58e6ee5fSAndroid Build Coastguard Worker 
5687*58e6ee5fSAndroid Build Coastguard Worker /**
5688*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_options_offset - get offset of the options sections in the file
5689*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5690*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_options_offset(struct tracecmd_input * handle)5691*58e6ee5fSAndroid Build Coastguard Worker size_t tracecmd_get_options_offset(struct tracecmd_input *handle)
5692*58e6ee5fSAndroid Build Coastguard Worker {
5693*58e6ee5fSAndroid Build Coastguard Worker 	return handle->options_start;
5694*58e6ee5fSAndroid Build Coastguard Worker }
5695*58e6ee5fSAndroid Build Coastguard Worker 
5696*58e6ee5fSAndroid Build Coastguard Worker /**
5697*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_trace_clock - return the saved trace clock
5698*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5699*58e6ee5fSAndroid Build Coastguard Worker  *
5700*58e6ee5fSAndroid Build Coastguard Worker  * Returns a string of the clock that was saved in the trace.dat file.
5701*58e6ee5fSAndroid Build Coastguard Worker  * The string should not be freed, as it points to the internal
5702*58e6ee5fSAndroid Build Coastguard Worker  * structure data.
5703*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_trace_clock(struct tracecmd_input * handle)5704*58e6ee5fSAndroid Build Coastguard Worker const char *tracecmd_get_trace_clock(struct tracecmd_input *handle)
5705*58e6ee5fSAndroid Build Coastguard Worker {
5706*58e6ee5fSAndroid Build Coastguard Worker 	return handle->trace_clock;
5707*58e6ee5fSAndroid Build Coastguard Worker }
5708*58e6ee5fSAndroid Build Coastguard Worker 
5709*58e6ee5fSAndroid Build Coastguard Worker /**
5710*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_cpustats - return the saved cpu stats
5711*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5712*58e6ee5fSAndroid Build Coastguard Worker  *
5713*58e6ee5fSAndroid Build Coastguard Worker  * Provides a method to extract the cpu stats saved in @handle.
5714*58e6ee5fSAndroid Build Coastguard Worker  *
5715*58e6ee5fSAndroid Build Coastguard Worker  * Returns a string of the cpu stats that was saved in the trace.dat file.
5716*58e6ee5fSAndroid Build Coastguard Worker  * The string should not be freed, as it points to the internal
5717*58e6ee5fSAndroid Build Coastguard Worker  * structure data.
5718*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_cpustats(struct tracecmd_input * handle)5719*58e6ee5fSAndroid Build Coastguard Worker const char *tracecmd_get_cpustats(struct tracecmd_input *handle)
5720*58e6ee5fSAndroid Build Coastguard Worker {
5721*58e6ee5fSAndroid Build Coastguard Worker 	return handle->cpustats;
5722*58e6ee5fSAndroid Build Coastguard Worker }
5723*58e6ee5fSAndroid Build Coastguard Worker 
5724*58e6ee5fSAndroid Build Coastguard Worker /**
5725*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_uname - return the saved name and kernel information
5726*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5727*58e6ee5fSAndroid Build Coastguard Worker  *
5728*58e6ee5fSAndroid Build Coastguard Worker  * Provides a method to extract the system information saved in @handle.
5729*58e6ee5fSAndroid Build Coastguard Worker  *
5730*58e6ee5fSAndroid Build Coastguard Worker  * Returns a string of the system information that was saved in the
5731*58e6ee5fSAndroid Build Coastguard Worker  * trace.dat file.
5732*58e6ee5fSAndroid Build Coastguard Worker  * The string should not be freed, as it points to the internal
5733*58e6ee5fSAndroid Build Coastguard Worker  * structure data.
5734*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_uname(struct tracecmd_input * handle)5735*58e6ee5fSAndroid Build Coastguard Worker const char *tracecmd_get_uname(struct tracecmd_input *handle)
5736*58e6ee5fSAndroid Build Coastguard Worker {
5737*58e6ee5fSAndroid Build Coastguard Worker 	return handle->uname;
5738*58e6ee5fSAndroid Build Coastguard Worker }
5739*58e6ee5fSAndroid Build Coastguard Worker 
5740*58e6ee5fSAndroid Build Coastguard Worker /**
5741*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_version - return the saved version information
5742*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5743*58e6ee5fSAndroid Build Coastguard Worker  *
5744*58e6ee5fSAndroid Build Coastguard Worker  * Provides a method to extract the version string saved in @handle.
5745*58e6ee5fSAndroid Build Coastguard Worker  *
5746*58e6ee5fSAndroid Build Coastguard Worker  * Returns a string of the version that was saved in the trace.dat file.
5747*58e6ee5fSAndroid Build Coastguard Worker  * The string should not be freed, as it points to the internal
5748*58e6ee5fSAndroid Build Coastguard Worker  * structure data.
5749*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_version(struct tracecmd_input * handle)5750*58e6ee5fSAndroid Build Coastguard Worker const char *tracecmd_get_version(struct tracecmd_input *handle)
5751*58e6ee5fSAndroid Build Coastguard Worker {
5752*58e6ee5fSAndroid Build Coastguard Worker 	return handle->version;
5753*58e6ee5fSAndroid Build Coastguard Worker }
5754*58e6ee5fSAndroid Build Coastguard Worker 
5755*58e6ee5fSAndroid Build Coastguard Worker /**
5756*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_cpu_file_size - return the saved cpu file size
5757*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5758*58e6ee5fSAndroid Build Coastguard Worker  * @cpu: cpu index
5759*58e6ee5fSAndroid Build Coastguard Worker  *
5760*58e6ee5fSAndroid Build Coastguard Worker  * Provides a method to extract the cpu file size saved in @handle.
5761*58e6ee5fSAndroid Build Coastguard Worker  *
5762*58e6ee5fSAndroid Build Coastguard Worker  * Returns the cpu file size saved in trace.dat file or (off64_t)-1 for
5763*58e6ee5fSAndroid Build Coastguard Worker  * invalid cpu index.
5764*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_cpu_file_size(struct tracecmd_input * handle,int cpu)5765*58e6ee5fSAndroid Build Coastguard Worker off64_t tracecmd_get_cpu_file_size(struct tracecmd_input *handle, int cpu)
5766*58e6ee5fSAndroid Build Coastguard Worker {
5767*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu < 0 || cpu >= handle->cpus)
5768*58e6ee5fSAndroid Build Coastguard Worker 		return (off64_t)-1;
5769*58e6ee5fSAndroid Build Coastguard Worker 	return handle->cpu_data[cpu].file_size;
5770*58e6ee5fSAndroid Build Coastguard Worker }
5771*58e6ee5fSAndroid Build Coastguard Worker 
5772*58e6ee5fSAndroid Build Coastguard Worker /**
5773*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_show_data_func - return the show data func
5774*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5775*58e6ee5fSAndroid Build Coastguard Worker  */
5776*58e6ee5fSAndroid Build Coastguard Worker tracecmd_show_data_func
tracecmd_get_show_data_func(struct tracecmd_input * handle)5777*58e6ee5fSAndroid Build Coastguard Worker tracecmd_get_show_data_func(struct tracecmd_input *handle)
5778*58e6ee5fSAndroid Build Coastguard Worker {
5779*58e6ee5fSAndroid Build Coastguard Worker 	return handle->show_data_func;
5780*58e6ee5fSAndroid Build Coastguard Worker }
5781*58e6ee5fSAndroid Build Coastguard Worker 
5782*58e6ee5fSAndroid Build Coastguard Worker /**
5783*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_set_show_data_func - set the show data func
5784*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5785*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_set_show_data_func(struct tracecmd_input * handle,tracecmd_show_data_func func)5786*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_set_show_data_func(struct tracecmd_input *handle,
5787*58e6ee5fSAndroid Build Coastguard Worker 				 tracecmd_show_data_func func)
5788*58e6ee5fSAndroid Build Coastguard Worker {
5789*58e6ee5fSAndroid Build Coastguard Worker 	handle->show_data_func = func;
5790*58e6ee5fSAndroid Build Coastguard Worker }
5791*58e6ee5fSAndroid Build Coastguard Worker 
5792*58e6ee5fSAndroid Build Coastguard Worker /**
5793*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_traceid - get the trace id of the session
5794*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5795*58e6ee5fSAndroid Build Coastguard Worker  *
5796*58e6ee5fSAndroid Build Coastguard Worker  * Returns the trace id, written in the trace file
5797*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_traceid(struct tracecmd_input * handle)5798*58e6ee5fSAndroid Build Coastguard Worker unsigned long long tracecmd_get_traceid(struct tracecmd_input *handle)
5799*58e6ee5fSAndroid Build Coastguard Worker {
5800*58e6ee5fSAndroid Build Coastguard Worker 	return handle->trace_id;
5801*58e6ee5fSAndroid Build Coastguard Worker }
5802*58e6ee5fSAndroid Build Coastguard Worker 
5803*58e6ee5fSAndroid Build Coastguard Worker /**
5804*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_first_ts - get the timestamp of the first recorded event
5805*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5806*58e6ee5fSAndroid Build Coastguard Worker  *
5807*58e6ee5fSAndroid Build Coastguard Worker  * Returns the timestamp of the first recorded event
5808*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_first_ts(struct tracecmd_input * handle)5809*58e6ee5fSAndroid Build Coastguard Worker unsigned long long tracecmd_get_first_ts(struct tracecmd_input *handle)
5810*58e6ee5fSAndroid Build Coastguard Worker {
5811*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long ts = 0;
5812*58e6ee5fSAndroid Build Coastguard Worker 	bool first = true;
5813*58e6ee5fSAndroid Build Coastguard Worker 	int i;
5814*58e6ee5fSAndroid Build Coastguard Worker 
5815*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < handle->cpus; i++) {
5816*58e6ee5fSAndroid Build Coastguard Worker 		/* Ignore empty buffers */
5817*58e6ee5fSAndroid Build Coastguard Worker 		if (!handle->cpu_data[i].size)
5818*58e6ee5fSAndroid Build Coastguard Worker 			continue;
5819*58e6ee5fSAndroid Build Coastguard Worker 		if (first || ts > handle->cpu_data[i].first_ts)
5820*58e6ee5fSAndroid Build Coastguard Worker 			ts = handle->cpu_data[i].first_ts;
5821*58e6ee5fSAndroid Build Coastguard Worker 		first = false;
5822*58e6ee5fSAndroid Build Coastguard Worker 	}
5823*58e6ee5fSAndroid Build Coastguard Worker 
5824*58e6ee5fSAndroid Build Coastguard Worker 	return ts;
5825*58e6ee5fSAndroid Build Coastguard Worker }
5826*58e6ee5fSAndroid Build Coastguard Worker 
5827*58e6ee5fSAndroid Build Coastguard Worker /**
5828*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_get_guest_cpumap - get the mapping of guest VCPU to host process
5829*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5830*58e6ee5fSAndroid Build Coastguard Worker  * @trace_id: ID of the guest tracing session
5831*58e6ee5fSAndroid Build Coastguard Worker  * @name: return, name of the guest
5832*58e6ee5fSAndroid Build Coastguard Worker  * @vcpu_count: return, number of VPUs
5833*58e6ee5fSAndroid Build Coastguard Worker  * @cpu_pid: return, array with guest VCPU to host process mapping
5834*58e6ee5fSAndroid Build Coastguard Worker  *
5835*58e6ee5fSAndroid Build Coastguard Worker  * Returns @name of the guest, number of VPUs (@vcpu_count)
5836*58e6ee5fSAndroid Build Coastguard Worker  * and array @cpu_pid with size @vcpu_count. Array index is VCPU id, array
5837*58e6ee5fSAndroid Build Coastguard Worker  * content is PID of the host process, running this VCPU.
5838*58e6ee5fSAndroid Build Coastguard Worker  *
5839*58e6ee5fSAndroid Build Coastguard Worker  * This information is stored in host trace.dat file
5840*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_get_guest_cpumap(struct tracecmd_input * handle,unsigned long long trace_id,const char ** name,int * vcpu_count,const int ** cpu_pid)5841*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_get_guest_cpumap(struct tracecmd_input *handle,
5842*58e6ee5fSAndroid Build Coastguard Worker 			      unsigned long long trace_id,
5843*58e6ee5fSAndroid Build Coastguard Worker 			      const char **name,
5844*58e6ee5fSAndroid Build Coastguard Worker 			      int *vcpu_count, const int **cpu_pid)
5845*58e6ee5fSAndroid Build Coastguard Worker {
5846*58e6ee5fSAndroid Build Coastguard Worker 	struct guest_trace_info	*guest = handle->guest;
5847*58e6ee5fSAndroid Build Coastguard Worker 
5848*58e6ee5fSAndroid Build Coastguard Worker 	while (guest) {
5849*58e6ee5fSAndroid Build Coastguard Worker 		if (guest->trace_id == trace_id)
5850*58e6ee5fSAndroid Build Coastguard Worker 			break;
5851*58e6ee5fSAndroid Build Coastguard Worker 		guest = guest->next;
5852*58e6ee5fSAndroid Build Coastguard Worker 	}
5853*58e6ee5fSAndroid Build Coastguard Worker 	if (!guest)
5854*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5855*58e6ee5fSAndroid Build Coastguard Worker 
5856*58e6ee5fSAndroid Build Coastguard Worker 	if (name)
5857*58e6ee5fSAndroid Build Coastguard Worker 		*name = guest->name;
5858*58e6ee5fSAndroid Build Coastguard Worker 	if (vcpu_count)
5859*58e6ee5fSAndroid Build Coastguard Worker 		*vcpu_count = guest->vcpu_count;
5860*58e6ee5fSAndroid Build Coastguard Worker 	if (cpu_pid)
5861*58e6ee5fSAndroid Build Coastguard Worker 		*cpu_pid = guest->cpu_pid;
5862*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
5863*58e6ee5fSAndroid Build Coastguard Worker }
5864*58e6ee5fSAndroid Build Coastguard Worker 
5865*58e6ee5fSAndroid Build Coastguard Worker /**
5866*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_enable_tsync - enable / disable the timestamps correction
5867*58e6ee5fSAndroid Build Coastguard Worker  * @handle: input handle for the trace.dat file
5868*58e6ee5fSAndroid Build Coastguard Worker  * @enable: enable / disable the timestamps correction
5869*58e6ee5fSAndroid Build Coastguard Worker  *
5870*58e6ee5fSAndroid Build Coastguard Worker  * Enables or disables timestamps correction on file load, using the array of
5871*58e6ee5fSAndroid Build Coastguard Worker  * recorded time offsets. If "enable" is true, but there are no time offsets,
5872*58e6ee5fSAndroid Build Coastguard Worker  * function fails and -1 is returned.
5873*58e6ee5fSAndroid Build Coastguard Worker  *
5874*58e6ee5fSAndroid Build Coastguard Worker  * Returns -1 in case of an error, or 0 otherwise
5875*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_enable_tsync(struct tracecmd_input * handle,bool enable)5876*58e6ee5fSAndroid Build Coastguard Worker int tracecmd_enable_tsync(struct tracecmd_input *handle, bool enable)
5877*58e6ee5fSAndroid Build Coastguard Worker {
5878*58e6ee5fSAndroid Build Coastguard Worker 	if (enable &&
5879*58e6ee5fSAndroid Build Coastguard Worker 	    (!handle->host.ts_offsets || !handle->host.cpu_count))
5880*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
5881*58e6ee5fSAndroid Build Coastguard Worker 
5882*58e6ee5fSAndroid Build Coastguard Worker 	handle->host.sync_enable = enable;
5883*58e6ee5fSAndroid Build Coastguard Worker 
5884*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
5885*58e6ee5fSAndroid Build Coastguard Worker }
5886*58e6ee5fSAndroid Build Coastguard Worker 
5887