From: compudj Date: Thu, 4 Aug 2005 23:02:46 +0000 (+0000) Subject: New ltt library X-Git-Tag: v0.12.20~2485 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=54ecbf38947e9b647b11a58b27cf65d3c0985693;p=lttv.git New ltt library git-svn-id: http://ltt.polymtl.ca/svn@1004 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/ltt/branches/poly/ltt-newlib/Makefile.am b/ltt/branches/poly/ltt-newlib/Makefile.am new file mode 100644 index 00000000..50dc8fb3 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/Makefile.am @@ -0,0 +1,28 @@ +# +# Makefile for LTT New generation user interface : plugins. +# +# Created by Mathieu Desnoyers on May 6, 2003 +# + +SUBDIRS = convert + +libdir = ${lttlibdir} + +AM_CFLAGS = $(GLIB_CFLAGS) +LIBS += $(GLIB_LIBS) + +lib_LTLIBRARIES = libtraceread.la +libtraceread_la_SOURCES = event.c facility.c parser.c tracefile.c type.c +noinst_HEADERS = parser.h ltt-private.h + +lttinclude_HEADERS = \ + compiler.h\ + event.h\ + facility.h\ + ltt.h\ + time.h\ + trace.h\ + type.h\ + ltt-types.h + +EXTRA_DIST = crc32.tab diff --git a/ltt/branches/poly/ltt-newlib/compiler.h b/ltt/branches/poly/ltt-newlib/compiler.h new file mode 100644 index 00000000..cef7a476 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/compiler.h @@ -0,0 +1,26 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Mathieu Desnoyers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef COMPILER_H +#define COMPILER_H + +/* Fast prediction if likely branches */ +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +#endif //COMPILER_H diff --git a/ltt/branches/poly/ltt-newlib/convert/LTTTypes.h b/ltt/branches/poly/ltt-newlib/convert/LTTTypes.h new file mode 100644 index 00000000..e493f84b --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/convert/LTTTypes.h @@ -0,0 +1,142 @@ +/* + * LTTTypes.h + * + * Copyright (C) 2000 Karim Yaghmour (karym@opersys.com). + * + * This is distributed under GPL. + * + * Header for LTT-secific types. + * + * History : + * K.Y. 07/09/2001, Added David Schleef's architecture independent ltt_set_bit/ltt_clear_bit/ltt_test_bit + * JAL, 05/01/2001, Modified PPC bit manipulation functions for x86 compatibility. + * (andy_lowe@mvista.com) + * K.Y., 31/05/2000, Initial typing. + */ + +#ifndef __TRACE_TOOLKIT_TYPES_HEADER__ +#define __TRACE_TOOLKIT_TYPES_HEADER__ + +#include +#include + +#if defined(sun) + +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +typedef unsigned int u_int32_t; +#ifdef _LP64 +typedef unsigned long u_int64_t; +#else /* _ILP32 */ +#if __STDC__ - 0 == 0 && !defined(_NO_LONGLONG) +typedef unsigned long long u_int64_t; +#endif /* __STDC__ - 0 == 0 && !defined(_NO_LONGLONG) */ +#endif /* _LP64 */ + +#endif /* defined(sun) */ + +extern __inline__ int ltt_set_bit(int nr, void * addr) +{ + unsigned char *p = addr; + unsigned char mask = 1 << (nr&7); + unsigned char old; + + p += nr>>3; + old = *p; + *p |= mask; + + return ((old & mask) != 0); +} + +extern __inline__ int ltt_clear_bit(int nr, void * addr) +{ + unsigned char *p = addr; + unsigned char mask = 1 << (nr&7); + unsigned char old; + + p += nr>>3; + old = *p; + *p &= ~mask; + + return ((old & mask) != 0); +} + +extern __inline__ int ltt_test_bit(int nr,void *addr) +{ + unsigned char *p = addr; + unsigned char mask = 1 << (nr&7); + + p += nr>>3; + + return ((*p & mask) != 0); +} + +/* Big-endian/little-endian conversion macros for cross-development. */ +#if TARGET_NATIVE +/* For native development, these conversion macros aren't needed. */ +#define BREV16(x) (x) +#define BREV32(x) (x) +#define BREV64(x) (x) +#define RFT8(db,x) (x) +#define RFT16(db,x) (x) +#define RFT32(db,x) (x) +#define RFT64(db,x) (x) + +/* Non-native development */ +#else + /* BREV16: byte-reverse a 16-bit integer */ +#define BREV16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)) + /* BREV32: byte-reverse a 32-bit integer */ +#define BREV32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \ + | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + /* BREV64: byte-reverse a 64-bit integer */ +#define BREV64(x) ((((x) & 0xff00000000000000) >> 56) \ + | (((x) & 0x00ff000000000000) >> 40) \ + | (((x) & 0x0000ff0000000000) >> 24) \ + | (((x) & 0x000000ff00000000) >> 8) \ + | (((x) & 0x00000000ff000000) << 8) \ + | (((x) & 0x0000000000ff0000) << 24) \ + | (((x) & 0x000000000000ff00) << 40) \ + | (((x) & 0x00000000000000ff) << 56)) + /* RFTn: Read From Trace + * Conditionally byte-reverse an 8-, 16-, 32-, or 64-bit integer + * based on the value of the ByteRev member of the trace database + * structure pointer passed as the first argument.. + */ +#define RFT8(db,x) (x) +#define RFT16(db,x) ((db)->ByteRev ? BREV16(x) : (x)) +#define RFT32(db,x) ((db)->ByteRev ? BREV32(x) : (x)) +#define RFT64(db,x) ((db)->ByteRev ? BREV64(x) : (x)) +#endif /* TRACE_TARGET_NATIVE */ + +#if !defined(sun) +/* Some type corrections, just in case */ +#ifndef uint8_t +#define uint8_t u_int8_t +#endif +#ifndef uint16_t +#define uint16_t u_int16_t +#endif +#ifndef uint32_t +#define uint32_t u_int32_t +#endif +#ifndef uint64_t +#define uint64_t u_int64_t +#endif +#endif /* !defined(sun) */ + +/* Structure packing */ +#if LTT_UNPACKED_STRUCTS +#define LTT_PACKED_STRUCT +#else +#define LTT_PACKED_STRUCT __attribute__ ((packed)) +#endif /* UNPACKED_STRUCTS */ + +/* Trace mask */ +typedef uint64_t trace_event_mask; + +/* Boolean stuff */ +//#define TRUE 1 +//#define FALSE 0 + +#endif /* __TRACE_TOOLKIT_TYPES_HEADER__ */ diff --git a/ltt/branches/poly/ltt-newlib/convert/LinuxEvents.h b/ltt/branches/poly/ltt-newlib/convert/LinuxEvents.h new file mode 100644 index 00000000..dfd0840c --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/convert/LinuxEvents.h @@ -0,0 +1,333 @@ +/* + * LinuxEvents.h + * + * Copyright (C) 2000, 2001, 2002 Karim Yaghmour (karym@opersys.com). + * + * This header is distributed under GPL. + * + * Linux events being traced. + * + * History : + * K.Y., 31/05/1999, Initial typing. + * + */ + +#ifndef __TRACE_TOOLKIT_LINUX_HEADER__ +#define __TRACE_TOOLKIT_LINUX_HEADER__ + +#include "LTTTypes.h" + +/* Traced events */ +#define TRACE_START 0 /* This is to mark the trace's start */ +#define TRACE_SYSCALL_ENTRY 1 /* Entry in a given system call */ +#define TRACE_SYSCALL_EXIT 2 /* Exit from a given system call */ +#define TRACE_TRAP_ENTRY 3 /* Entry in a trap */ +#define TRACE_TRAP_EXIT 4 /* Exit from a trap */ +#define TRACE_IRQ_ENTRY 5 /* Entry in an irq */ +#define TRACE_IRQ_EXIT 6 /* Exit from an irq */ +#define TRACE_SCHEDCHANGE 7 /* Scheduling change */ +#define TRACE_KERNEL_TIMER 8 /* The kernel timer routine has been called */ +#define TRACE_SOFT_IRQ 9 /* Hit key part of soft-irq management */ +#define TRACE_PROCESS 10 /* Hit key part of process management */ +#define TRACE_FILE_SYSTEM 11 /* Hit key part of file system */ +#define TRACE_TIMER 12 /* Hit key part of timer management */ +#define TRACE_MEMORY 13 /* Hit key part of memory management */ +#define TRACE_SOCKET 14 /* Hit key part of socket communication */ +#define TRACE_IPC 15 /* Hit key part of inter-process communication */ +#define TRACE_NETWORK 16 /* Hit key part of network communication */ + +#define TRACE_BUFFER_START 17 /* Mark the begining of a trace buffer */ +#define TRACE_BUFFER_END 18 /* Mark the ending of a trace buffer */ +#define TRACE_NEW_EVENT 19 /* New event type */ +#define TRACE_CUSTOM 20 /* Custom event */ + +#define TRACE_CHANGE_MASK 21 /* Change in event mask */ +#define TRACE_HEARTBEAT 22 /* Heartbeat event */ + +/* Number of traced events */ +#define TRACE_MAX TRACE_HEARTBEAT + +/* Architecture types */ +#define TRACE_ARCH_TYPE_I386 1 /* i386 system */ +#define TRACE_ARCH_TYPE_PPC 2 /* PPC system */ +#define TRACE_ARCH_TYPE_SH 3 /* SH system */ +#define TRACE_ARCH_TYPE_S390 4 /* S/390 system */ +#define TRACE_ARCH_TYPE_MIPS 5 /* MIPS system */ +#define TRACE_ARCH_TYPE_ARM 6 /* ARM system */ + +/* Standard definitions for variants */ +#define TRACE_ARCH_VARIANT_NONE 0 /* Main architecture implementation */ + +/* PowerPC variants */ +#define TRACE_ARCH_VARIANT_PPC_4xx 1 /* 4xx systems (IBM embedded series) */ +#define TRACE_ARCH_VARIANT_PPC_6xx 2 /* 6xx/7xx/74xx/8260/POWER3 systems (desktop flavor) */ +#define TRACE_ARCH_VARIANT_PPC_8xx 3 /* 8xx system (Motoral embedded series) */ +#define TRACE_ARCH_VARIANT_PPC_ISERIES 4 /* 8xx system (iSeries) */ + +/* System types */ +#define TRACE_SYS_TYPE_VANILLA_LINUX 1 /* Vanilla linux kernel */ +#define TRACE_SYS_TYPE_RTAI_LINUX 2 /* RTAI patched linux kernel */ + +/* The information logged when the tracing is started */ +#define TRACER_MAGIC_NUMBER 0x00D6B7ED /* That day marks an important historical event ... */ +#define TRACER_SUP_VERSION_MAJOR 2 /* Major version number */ + +/* Minimum information contained in any trace start event */ +typedef struct _trace_start_any +{ + uint32_t MagicNumber; /* Magic number to identify a trace */ + uint32_t ArchType; /* Type of architecture */ + uint32_t ArchVariant; /* Variant of the given type of architecture */ + uint32_t SystemType; /* Operating system type */ + uint8_t MajorVersion; /* Major version of trace */ + uint8_t MinorVersion; /* Minor version of trace */ + +} LTT_PACKED_STRUCT trace_start_any; + +typedef struct _trace_start_2_2 +{ + uint32_t MagicNumber; /* Magic number to identify a trace */ + uint32_t ArchType; /* Type of architecture */ + uint32_t ArchVariant; /* Variant of the given type of architecture */ + uint32_t SystemType; /* Operating system type */ + uint8_t MajorVersion; /* Major version of trace */ + uint8_t MinorVersion; /* Minor version of trace */ + + uint32_t BufferSize; /* Size of buffers */ + trace_event_mask EventMask; /* The event mask */ + trace_event_mask DetailsMask; /* Are the event details logged */ + uint8_t LogCPUID; /* Is the CPUID logged */ + uint8_t UseTSC; /* Are we using TSCs or time deltas */ + +} LTT_PACKED_STRUCT trace_start_2_2; + +typedef struct _trace_start_2_3 +{ + uint32_t MagicNumber; /* Magic number to identify a trace */ + uint32_t ArchType; /* Type of architecture */ + uint32_t ArchVariant; /* Variant of the given type of architecture */ + uint32_t SystemType; /* Operating system type */ + uint8_t MajorVersion; /* Major version of trace */ + uint8_t MinorVersion; /* Minor version of trace */ + + uint32_t BufferSize; /* Size of buffers */ + trace_event_mask EventMask; /* The event mask */ + trace_event_mask DetailsMask; /* Are the event details logged */ + uint8_t LogCPUID; /* Is the CPUID logged */ + uint8_t UseTSC; /* Are we using TSCs or time deltas */ + + uint8_t FlightRecorder; /* Is this a flight recorder trace ? */ +} LTT_PACKED_STRUCT trace_start_2_3; + +/* TRACE_SYSCALL_ENTRY */ +typedef struct _trace_syscall_entry +{ + uint8_t syscall_id; /* Syscall entry number in entry.S */ + uint32_t address; /* Address from which call was made */ +} LTT_PACKED_STRUCT trace_syscall_entry; +#define SYSCALL_EVENT(X) ((trace_syscall_entry*)X) + +/* TRACE_TRAP_ENTRY */ +typedef struct _trace_trap_entry +{ + uint16_t trap_id; /* Trap number */ + uint32_t address; /* Address where trap occured */ +} LTT_PACKED_STRUCT trace_trap_entry; +typedef struct _trace_trap_entry_s390 +{ + uint64_t trap_id; /* Trap number */ + uint32_t address; /* Address where trap occured */ +} LTT_PACKED_STRUCT trace_trap_entry_s390; +#define TRAP_EVENT(X) ((trace_trap_entry*)X) +#define TRAP_EVENT_S390(X) ((trace_trap_entry_s390*)X) + +/* TRACE_IRQ_ENTRY */ +typedef struct _trace_irq_entry +{ + uint8_t irq_id; /* IRQ number */ + uint8_t kernel; /* Are we executing kernel code */ +} LTT_PACKED_STRUCT trace_irq_entry; +#define IRQ_EVENT(X) ((trace_irq_entry*)X) + +/* TRACE_SCHEDCHANGE */ +typedef struct _trace_schedchange +{ + uint32_t out; /* Outgoing process */ + uint32_t in; /* Incoming process */ + uint32_t out_state; /* Outgoing process' state */ +} LTT_PACKED_STRUCT trace_schedchange; +#define SCHED_EVENT(X) ((trace_schedchange*)X) + +/* TRACE_SOFT_IRQ */ +#define TRACE_SOFT_IRQ_BOTTOM_HALF 1 /* Conventional bottom-half */ +#define TRACE_SOFT_IRQ_SOFT_IRQ 2 /* Real soft-irq */ +#define TRACE_SOFT_IRQ_TASKLET_ACTION 3 /* Tasklet action */ +#define TRACE_SOFT_IRQ_TASKLET_HI_ACTION 4 /* Tasklet hi-action */ +typedef struct _trace_soft_irq +{ + uint8_t event_sub_id; /* Soft-irq event Id */ + uint32_t event_data; /* Data associated with event */ +} LTT_PACKED_STRUCT trace_soft_irq; +#define SOFT_IRQ_EVENT(X) ((trace_soft_irq*)X) + +/* TRACE_PROCESS */ +#define TRACE_PROCESS_KTHREAD 1 /* Creation of a kernel thread */ +#define TRACE_PROCESS_FORK 2 /* A fork or clone occured */ +#define TRACE_PROCESS_EXIT 3 /* An exit occured */ +#define TRACE_PROCESS_WAIT 4 /* A wait occured */ +#define TRACE_PROCESS_SIGNAL 5 /* A signal has been sent */ +#define TRACE_PROCESS_WAKEUP 6 /* Wake up a process */ +#define TRACE_PROCESS_RELEASE 7 /* A task struct has been released */ + +typedef struct _trace_process +{ + uint8_t event_sub_id; /* Process event ID */ + uint32_t event_data1; /* Data associated with event */ + uint32_t event_data2; +} LTT_PACKED_STRUCT trace_process; +#define PROC_EVENT(X) ((trace_process*)X) + +/* TRACE_FILE_SYSTEM */ +#define TRACE_FILE_SYSTEM_BUF_WAIT_START 1 /* Starting to wait for a data buffer */ +#define TRACE_FILE_SYSTEM_BUF_WAIT_END 2 /* End to wait for a data buffer */ +#define TRACE_FILE_SYSTEM_EXEC 3 /* An exec occured */ +#define TRACE_FILE_SYSTEM_OPEN 4 /* An open occured */ +#define TRACE_FILE_SYSTEM_CLOSE 5 /* A close occured */ +#define TRACE_FILE_SYSTEM_READ 6 /* A read occured */ +#define TRACE_FILE_SYSTEM_WRITE 7 /* A write occured */ +#define TRACE_FILE_SYSTEM_SEEK 8 /* A seek occured */ +#define TRACE_FILE_SYSTEM_IOCTL 9 /* An ioctl occured */ +#define TRACE_FILE_SYSTEM_SELECT 10 /* A select occured */ +#define TRACE_FILE_SYSTEM_POLL 11 /* A poll occured */ +typedef struct _trace_file_system +{ + uint8_t event_sub_id; /* File system event ID */ + uint32_t event_data1; /* Event data */ + uint32_t event_data2; /* Event data 2 */ + char* file_name; /* Name of file operated on */ +} LTT_PACKED_STRUCT trace_file_system; +#define FS_EVENT(X) ((trace_file_system*)X) +#define FS_EVENT_FILENAME(X) ((char*) ((X) + sizeof(trace_file_system))) + +/* TRACE_TIMER */ +#define TRACE_TIMER_EXPIRED 1 /* Timer expired */ +#define TRACE_TIMER_SETITIMER 2 /* Setting itimer occurred */ +#define TRACE_TIMER_SETTIMEOUT 3 /* Setting sched timeout occurred */ +typedef struct _trace_timer +{ + uint8_t event_sub_id; /* Timer event ID */ + uint8_t event_sdata; /* Short data */ + uint32_t event_data1; /* Data associated with event */ + uint32_t event_data2; +} LTT_PACKED_STRUCT trace_timer; +#define TIMER_EVENT(X) ((trace_timer*)X) + +/* TRACE_MEMORY */ +#define TRACE_MEMORY_PAGE_ALLOC 1 /* Allocating pages */ +#define TRACE_MEMORY_PAGE_FREE 2 /* Freing pages */ +#define TRACE_MEMORY_SWAP_IN 3 /* Swaping pages in */ +#define TRACE_MEMORY_SWAP_OUT 4 /* Swaping pages out */ +#define TRACE_MEMORY_PAGE_WAIT_START 5 /* Start to wait for page */ +#define TRACE_MEMORY_PAGE_WAIT_END 6 /* End to wait for page */ +typedef struct _trace_memory +{ + uint8_t event_sub_id; /* Memory event ID */ + unsigned long event_data; /* Data associated with event */ +} LTT_PACKED_STRUCT trace_memory; +#define MEM_EVENT(X) ((trace_memory*)X) + +/* TRACE_SOCKET */ +#define TRACE_SOCKET_CALL 1 /* A socket call occured */ +#define TRACE_SOCKET_CREATE 2 /* A socket has been created */ +#define TRACE_SOCKET_SEND 3 /* Data was sent to a socket */ +#define TRACE_SOCKET_RECEIVE 4 /* Data was read from a socket */ +typedef struct _trace_socket +{ + uint8_t event_sub_id; /* Socket event ID */ + uint32_t event_data1; /* Data associated with event */ + uint32_t event_data2; /* Data associated with event */ +} LTT_PACKED_STRUCT trace_socket; +#define SOCKET_EVENT(X) ((trace_socket*)X) + +/* TRACE_IPC */ +#define TRACE_IPC_CALL 1 /* A System V IPC call occured */ +#define TRACE_IPC_MSG_CREATE 2 /* A message queue has been created */ +#define TRACE_IPC_SEM_CREATE 3 /* A semaphore was created */ +#define TRACE_IPC_SHM_CREATE 4 /* A shared memory segment has been created */ +typedef struct _trace_ipc +{ + uint8_t event_sub_id; /* IPC event ID */ + uint32_t event_data1; /* Data associated with event */ + uint32_t event_data2; /* Data associated with event */ +} LTT_PACKED_STRUCT trace_ipc; +#define IPC_EVENT(X) ((trace_ipc*)X) + +/* TRACE_NETWORK */ +#define TRACE_NETWORK_PACKET_IN 1 /* A packet came in */ +#define TRACE_NETWORK_PACKET_OUT 2 /* A packet was sent */ +typedef struct _trace_network +{ + uint8_t event_sub_id; /* Network event ID */ + uint32_t event_data; /* Event data */ +} LTT_PACKED_STRUCT trace_network; +#define NET_EVENT(X) ((trace_network*)X) + +/* Start of trace buffer information */ +typedef struct _trace_buffer_start +{ + struct timeval Time; /* Time stamp of this buffer */ + uint32_t TSC; /* TSC of this buffer, if applicable */ + uint32_t ID; /* Unique buffer ID */ +} LTT_PACKED_STRUCT trace_buffer_start; + +/* End of trace buffer information */ +typedef struct _trace_buffer_end +{ + struct timeval Time; /* Time stamp of this buffer */ + uint32_t TSC; /* TSC of this buffer, if applicable */ +} LTT_PACKED_STRUCT trace_buffer_end; + +/* Maximal size a custom event can have */ +#define CUSTOM_EVENT_MAX_SIZE 8192 + +/* String length limits for custom events creation */ +#define CUSTOM_EVENT_TYPE_STR_LEN 20 +#define CUSTOM_EVENT_DESC_STR_LEN 100 +#define CUSTOM_EVENT_FORM_STR_LEN 256 + +/* Type of custom event formats */ +#define CUSTOM_EVENT_FORMAT_TYPE_NONE 0 +#define CUSTOM_EVENT_FORMAT_TYPE_STR 1 +#define CUSTOM_EVENT_FORMAT_TYPE_HEX 2 +#define CUSTOM_EVENT_FORMAT_TYPE_XML 3 +#define CUSTOM_EVENT_FORMAT_TYPE_IBM 4 + +typedef struct _trace_new_event +{ + /* Basics */ + uint32_t id; /* Custom event ID */ + char type[CUSTOM_EVENT_TYPE_STR_LEN]; /* Event type description */ + char desc[CUSTOM_EVENT_DESC_STR_LEN]; /* Detailed event description */ + + /* Custom formatting */ + uint32_t format_type; /* Type of formatting */ + char form[CUSTOM_EVENT_FORM_STR_LEN]; /* Data specific to format */ +} LTT_PACKED_STRUCT trace_new_event; +#define NEW_EVENT(X) ((trace_new_event*) X) + +typedef struct _trace_custom +{ + uint32_t id; /* Event ID */ + uint32_t data_size; /* Size of data recorded by event */ + void* data; /* Data recorded by event */ +} LTT_PACKED_STRUCT trace_custom; +#define CUSTOM_EVENT(X) ((trace_custom*) X) + +/* TRACE_CHANGE_MASK */ +typedef struct _trace_change_mask +{ + trace_event_mask mask; /* Event mask */ +} LTT_PACKED_STRUCT trace_change_mask; +#define CHMASK_EVENT(X) ((trace_change_mask*) X) + +#endif /* __TRACE_TOOLKIT_LINUX_HEADER__ */ diff --git a/ltt/branches/poly/ltt-newlib/convert/Makefile.am b/ltt/branches/poly/ltt-newlib/convert/Makefile.am new file mode 100644 index 00000000..6dbec8e5 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/convert/Makefile.am @@ -0,0 +1,12 @@ +AM_CFLAGS = $(GLIB_CFLAGS) +LIBS += $(GLIB_LIBS) $(M_LIBS) + +bin_PROGRAMS = convert + +convert_SOURCES = convert.c + +noinst_HEADERS = LTTTypes.h LinuxEvents.h + +EXTRA_DIST = core.xml sysInfo README +convertdir = $(pkgdatadir)/convert +convert_DATA = core.xml sysInfo README diff --git a/ltt/branches/poly/ltt-newlib/convert/README b/ltt/branches/poly/ltt-newlib/convert/README new file mode 100644 index 00000000..e3af7f7b --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/convert/README @@ -0,0 +1,19 @@ +The application 'convert' is used to convert an old format tracefile into a new +format tracefile. It has several commandline parameters, the first is process file +name, the second is a number (the number of cpu in the machine), the third is +the first tracefile name(corresponding to the first cpu), the fourth is the +second tracefile name(corresponding to the second cpu), the fifth is ..., +the last one is root directory for the new trace (this can be omitted, +by default it is 'foo') + +The command line looks like this: + ./convert processfile_name the_number_of_cpu first_tracefile_name, ..., foo_dir + +There is also a script file 'sysInfo' which is used to get system information +from your local machine, the information is saved in 'sysInfo.out' which will +be read by 'convert' later. If the old tracefile is generated by other machine, +then the 'sysInfo.out' should be gotten from that machine. + +'core.xml' is a facility file, after run 'convert', it needs to be copied to +'foo_dir/eventdefs' directory + diff --git a/ltt/branches/poly/ltt-newlib/convert/convert.c b/ltt/branches/poly/ltt-newlib/convert/convert.c new file mode 100644 index 00000000..b9812cc5 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/convert/convert.c @@ -0,0 +1,764 @@ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "LTTTypes.h" +#include "LinuxEvents.h" + +#define TRACE_HEARTBEAT_ID 19 +#define PROCESS_FORK_ID 20 +#define PROCESS_EXIT_ID 21 + +#define INFO_ENTRY 9 +#define OVERFLOW_FIGURE 0x100000000ULL + +typedef struct _new_process +{ + uint32_t event_data1; /* Data associated with event */ + uint32_t event_data2; +} LTT_PACKED_STRUCT new_process; + +#define write_to_buffer(DEST, SRC, SIZE) \ +do\ +{\ + memcpy(DEST, SRC, SIZE);\ + DEST += SIZE;\ +} while(0); + +int readFile(int fd, void * buf, size_t size, char * mesg) +{ + ssize_t nbBytes = read(fd, buf, size); + + if((size_t)nbBytes != size) { + if(nbBytes < 0) { + perror("Error in readFile : "); + } else { + printf("%s\n",mesg); + } + exit(1); + } + return 0; +} + +void getDataEndianType(char * size, char * endian) +{ + int i = 1; + char c = (char) i; + int sizeInt=sizeof(int), sizeLong=sizeof(long), sizePointer=sizeof(void *); + + if(c == 1) strcpy(endian,"LITTLE_ENDIAN"); + else strcpy(endian, "BIG_ENDIAN"); + + if(sizeInt == 2 && sizeLong == 4 && sizePointer == 4) + strcpy(size,"LP32"); + else if(sizeInt == 4 && sizeLong == 4 && sizePointer == 4) + strcpy(size,"ILP32"); + else if(sizeInt == 4 && sizeLong == 8 && sizePointer == 8) + strcpy(size,"LP64"); + else if(sizeInt == 8 && sizeLong == 8 && sizePointer == 8) + strcpy(size,"ILP64"); + else strcpy(size,"UNKNOWN"); +} + +#define BUFFER_SIZE 80 + +typedef struct _buffer_start{ + uint32_t seconds; + uint32_t nanoseconds; + uint64_t cycle_count; + uint32_t block_id; +} __attribute__ ((packed)) buffer_start; + +typedef struct _buffer_end{ + uint32_t seconds; + uint32_t nanoseconds; + uint64_t cycle_count; + uint32_t block_id; +} __attribute__ ((packed)) buffer_end; + + +typedef struct _heartbeat{ + uint32_t seconds; + uint32_t nanoseconds; + uint64_t cycle_count; +} __attribute__ ((packed)) heartbeat; + + +int main(int argc, char ** argv){ + + int fd, fdCpu; + FILE * fp; + int fdFac, fdIntr, fdProc; + char arch_size[BUFFER_SIZE]; + char endian[BUFFER_SIZE]; + char node_name[BUFFER_SIZE]; + char domainname[BUFFER_SIZE]; + char kernel_name[BUFFER_SIZE]; + char kernel_release[BUFFER_SIZE]; + char kernel_version[BUFFER_SIZE]; + char machine[BUFFER_SIZE]; + char processor[BUFFER_SIZE]; + char hardware_platform[BUFFER_SIZE]; + char operating_system[BUFFER_SIZE]; + int cpu; + int ltt_block_size=0; + int ltt_major_version=0; + int ltt_minor_version=0; + int ltt_log_cpu; + guint ltt_trace_start_size = 0; + char buf[BUFFER_SIZE]; + int i, k; + + uint8_t cpu_id; + + char foo[4*BUFFER_SIZE]; + char foo_eventdefs[4*BUFFER_SIZE]; + char foo_control[4*BUFFER_SIZE]; + char foo_cpu[4*BUFFER_SIZE]; + char foo_info[4*BUFFER_SIZE]; + + char foo_control_facilities[4*BUFFER_SIZE]; + char foo_control_processes[4*BUFFER_SIZE]; + char foo_control_interrupts[4*BUFFER_SIZE]; + char foo_info_system[4*BUFFER_SIZE]; + + struct stat lTDFStat; + off_t file_size; + int block_number, block_size; + char * buffer, *buf_out, cpuStr[4*BUFFER_SIZE]; + char * buf_fac, * buf_intr, * buf_proc; + void * write_pos, *write_pos_fac, * write_pos_intr, *write_pos_proc; + trace_start_any *tStart; + trace_buffer_start *tBufStart; + trace_buffer_end *tBufEnd; + trace_file_system * tFileSys; + uint16_t newId, startId, tmpId; + uint8_t evId; + uint32_t time_delta, startTimeDelta; + void * cur_pos, *end_pos; + buffer_start start, start_proc, start_intr; + buffer_end end, end_proc, end_intr; + heartbeat beat; + uint64_t adaptation_tsc; // (Mathieu) + uint32_t size_lost; + int reserve_size = sizeof(buffer_start) + + sizeof(buffer_end) + //buffer_end event + sizeof(uint32_t); //lost size + int nb_para; + + new_process process; + + if(argc < 4){ + printf("Usage : ./convert processfile_name number_of_cpu tracefile1 tracefile2 ... trace_creation_directory\n"); + printf("For more details, see README.\n"); + exit(1); + } + + cpu = atoi(argv[2]); + printf("cpu number = %d\n", cpu); + nb_para = 3 + cpu; + + if(argc != nb_para && argc != nb_para+1){ + printf("need trace files and cpu number or root directory for the new tracefile\n"); + exit(1); + } + + if(argc == nb_para){ + strcpy(foo, "foo"); + strcpy(foo_eventdefs, "foo/eventdefs"); + strcpy(foo_control, "foo/control"); + strcpy(foo_cpu, "foo/cpu"); + strcpy(foo_info, "foo/info"); + }else{ + strcpy(foo, argv[nb_para]); + strcpy(foo_eventdefs, argv[nb_para]); + strcat(foo_eventdefs,"/eventdefs"); + strcpy(foo_control, argv[nb_para]); + strcat(foo_control,"/control"); + strcpy(foo_cpu, argv[nb_para]); + strcat(foo_cpu,"/cpu"); + strcpy(foo_info, argv[nb_para]); + strcat(foo_info,"/info"); + } + strcpy(foo_control_facilities, foo_control); + strcat(foo_control_facilities,"/facilities"); + strcpy(foo_control_processes, foo_control); + strcat(foo_control_processes, "/processes"); + strcpy(foo_control_interrupts, foo_control); + strcat(foo_control_interrupts, "/interrupts"); + strcpy(foo_info_system, foo_info); + strcat(foo_info_system, "/system.xml"); + + + getDataEndianType(arch_size, endian); + printf("Arch_size: %s, Endian: %s\n", arch_size, endian); + + fp = fopen("sysInfo.out","r"); + if(!fp){ + g_error("Unable to open file sysInfo.out\n"); + } + + for(i=0;iMagicNumber != TRACER_MAGIC_NUMBER) + g_error("Trace magic number does not match : %lx, should be %lx", + tStart->MagicNumber, TRACER_MAGIC_NUMBER); + if(tStart->MajorVersion != TRACER_SUP_VERSION_MAJOR) + g_error("Trace Major number does match : %hu, should be %u", + tStart->MajorVersion, TRACER_SUP_VERSION_MAJOR); + + startId = newId; + startTimeDelta = time_delta; + start.seconds = tBufStart->Time.tv_sec; + /* Fix (Mathieu) */ + start.nanoseconds = tBufStart->Time.tv_usec * 1000; + start.cycle_count = tBufStart->TSC; + start.block_id = tBufStart->ID; + end.block_id = start.block_id; + + + g_printf("Trace version %hu.%hu detected\n", + tStart->MajorVersion, + tStart->MinorVersion); + if(tStart->MinorVersion == 2) { + trace_start_2_2* tStart_2_2 = (trace_start_2_2*)tStart; + ltt_major_version = tStart_2_2->MajorVersion; + ltt_minor_version = tStart_2_2->MinorVersion; + ltt_block_size = tStart_2_2->BufferSize; + ltt_log_cpu = tStart_2_2->LogCPUID; + ltt_trace_start_size = sizeof(trace_start_2_2); + /* Verify if it's a broken 2.2 format */ + if(*(uint8_t*)(cur_pos + sizeof(trace_start_2_2)) == 0) { + /* Cannot have two trace start events. We cannot detect the problem + * if the flight recording flag is set to 1, as it conflicts + * with TRACE_SYSCALL_ENTRY. + */ + g_warning("This is a 2.3 trace format that has a 2.2 tag. Please upgrade your kernel"); + g_printf("Processing the trace as a 2.3 format\n"); + + tStart->MinorVersion = 3; + } + } + + if(tStart->MinorVersion == 3) { + trace_start_2_3* tStart_2_3 = (trace_start_2_3*)tStart; + ltt_major_version = tStart_2_3->MajorVersion; + ltt_minor_version = tStart_2_3->MinorVersion; + ltt_block_size = tStart_2_3->BufferSize; + ltt_log_cpu = tStart_2_3->LogCPUID; + ltt_trace_start_size = sizeof(trace_start_2_3); + /* We do not use the flight recorder information for now, because we + * never use the .proc file anyway */ + } + + if(ltt_trace_start_size == 0) + g_error("Minor version unknown : %hu. Supported minors : 2, 3", + tStart->MinorVersion); + + block_size = ltt_block_size;//FIXME + block_number = file_size/ltt_block_size; + + g_free(buffer); + buffer = g_new(char, ltt_block_size); + buf_fac = g_new(char, block_size); + write_pos_fac = buf_fac; + buf_intr = g_new(char, block_size); + write_pos_intr = buf_intr; + buf_proc = g_new(char, block_size); + write_pos_proc = buf_proc; + + buf_out = g_new(char, block_size); + write_pos = buf_out; + sprintf(cpuStr,"%s/%d",foo_cpu,k); + fdCpu = open(cpuStr, O_CREAT | O_RDWR | O_TRUNC,S_IRUSR |S_IWUSR | S_IRGRP | S_IROTH); //for cpu k + if(fdCpu < 0) g_error("Unable to open cpu file %d\n", k); + lseek(fd,0,SEEK_SET); + + for(i=0;iTime.tv_sec; + /* usec -> nsec (Mathieu) */ + start.nanoseconds = tBufStart->Time.tv_usec * 1000; + start.block_id = tBufStart->ID; + end.block_id = start.block_id; + + end_pos = buffer + ltt_block_size; //end of the buffer + size_lost = *(uint32_t*)(end_pos - sizeof(uint32_t)); + + end_pos = buffer + ltt_block_size - size_lost ; //buffer_end event + if(ltt_log_cpu){ + tBufEnd = (trace_buffer_end*)(end_pos + 2 * sizeof(uint8_t)+sizeof(uint32_t)); + }else{ + tBufEnd = (trace_buffer_end*)(end_pos+sizeof(uint8_t)+sizeof(uint32_t)); + } + end.seconds = tBufEnd->Time.tv_sec; + /* usec -> nsec (Mathieu) */ + end.nanoseconds = tBufEnd->Time.tv_usec * 1000; + // only 32 bits :( + //end.cycle_count = tBufEnd->TSC; + + //skip buffer start and trace start events + if(i==0) { + //the first block + adaptation_tsc = (uint64_t)tBufStart->TSC; + cur_pos = buffer + sizeof(trace_buffer_start) + + ltt_trace_start_size + + 2*(sizeof(uint8_t) + + sizeof(uint16_t)+sizeof(uint32_t)); + } else { + //other blocks + cur_pos = buffer + sizeof(trace_buffer_start) + + sizeof(uint8_t) + + sizeof(uint16_t)+sizeof(uint32_t); + + /* Fix (Mathieu) */ + if(time_delta < (0xFFFFFFFFULL&adaptation_tsc)) { + /* Overflow */ + adaptation_tsc = (adaptation_tsc&0xFFFFFFFF00000000ULL) + + 0x100000000ULL + + (uint64_t)time_delta; + } else { + /* No overflow */ + adaptation_tsc = (adaptation_tsc&0xFFFFFFFF00000000ULL) + time_delta; + } + + } + start.cycle_count = adaptation_tsc; + + //write start block event + write_to_buffer(write_pos,(void*)&startId, sizeof(uint16_t)); + write_to_buffer(write_pos,(void*)&startTimeDelta, sizeof(uint32_t)); + write_to_buffer(write_pos,(void*)&start, sizeof(buffer_start)); + + //write start block event into processes and interrupts files + write_to_buffer(write_pos_intr,(void*)&startId, sizeof(uint16_t)); + write_to_buffer(write_pos_intr,(void*)&startTimeDelta, sizeof(uint32_t)); + start_intr = start; + start_intr.nanoseconds -= 20; + write_to_buffer(write_pos_intr,(void*)&start_intr, sizeof(buffer_start)); + + write_to_buffer(write_pos_proc,(void*)&startId, sizeof(uint16_t)); + write_to_buffer(write_pos_proc,(void*)&startTimeDelta, sizeof(uint32_t)); + start_proc = start; + start_proc.nanoseconds -= 40; + write_to_buffer(write_pos_proc,(void*)&start_proc, sizeof(buffer_start)); + + //parse *.proc file to get process and irq info + if(i == 0){ + int lIntID; /* Interrupt ID */ + int lPID, lPPID; /* Process PID and Parent PID */ + char lName[256]; /* Process name */ + FILE * fProc; + uint16_t defaultId; + trace_irq_entry irq; + + fProc = fopen(argv[1],"r"); + if(!fProc){ + g_error("Unable to open file %s\n", argv[1]); + } + + while(fscanf(fProc, "PID: %d; PPID: %d; NAME: %s\n", &lPID, &lPPID, lName) > 0){ + defaultId = PROCESS_FORK_ID; + process.event_data1 = lPID; + process.event_data2 = lPPID; + write_to_buffer(write_pos_proc,(void*)&defaultId, sizeof(uint16_t)); + write_to_buffer(write_pos_proc,(void*)&startTimeDelta, sizeof(uint32_t)); + write_to_buffer(write_pos_proc,(void*)&process, sizeof(new_process)); + } + + while(fscanf(fProc, "IRQ: %d; NAME: ", &lIntID) > 0){ + /* Read 'til the end of the line */ + fgets(lName, 200, fProc); + + defaultId = TRACE_IRQ_ENTRY; + irq.irq_id = lIntID; + irq.kernel = 1; + write_to_buffer(write_pos_intr,(void*)&defaultId, sizeof(uint16_t)); + write_to_buffer(write_pos_intr,(void*)&startTimeDelta, sizeof(uint32_t)); + write_to_buffer(write_pos_intr,(void*)&irq, sizeof(trace_irq_entry)); + } + fclose(fProc); + } + + while(1){ + int event_size; + uint64_t timeDelta; + uint8_t subId; + + if(ltt_log_cpu){ + cpu_id = *(uint8_t*)cur_pos; + cur_pos += sizeof(uint8_t); + } + evId = *(uint8_t *)cur_pos; + newId = evId; + if(evId == TRACE_HEARTBEAT) { + newId = TRACE_HEARTBEAT_ID; + } + cur_pos += sizeof(uint8_t); + time_delta = *(uint32_t*)cur_pos; + cur_pos += sizeof(uint32_t); + + + //write event_id and time_delta + write_to_buffer(write_pos,(void*)&newId,sizeof(uint16_t)); + write_to_buffer(write_pos,(void*)&time_delta, sizeof(uint32_t)); + + /* Fix (Mathieu) */ + if(time_delta < (0xFFFFFFFFULL&adaptation_tsc)) { + /* Overflow */ + adaptation_tsc = (adaptation_tsc&0xFFFFFFFF00000000ULL) + 0x100000000ULL + + (uint64_t)time_delta; + } else { + /* No overflow */ + adaptation_tsc = (adaptation_tsc&0xFFFFFFFF00000000ULL) + time_delta; + } + + + if(evId == TRACE_BUFFER_END){ +#if 0 + /* Fix (Mathieu) */ + if(time_delta < (0xFFFFFFFFULL&adaptation_tsc)) { + /* Overflow */ + adaptation_tsc = (adaptation_tsc&0xFFFFFFFF00000000ULL) + 0x100000000ULL + + (uint64_t)time_delta; + } else { + /* No overflow */ + adaptation_tsc = (adaptation_tsc&0xFFFFFFFF00000000ULL) + time_delta; + } +#endif //0 + end.cycle_count = adaptation_tsc; + int size = (void*)buf_out + block_size - write_pos + - sizeof(buffer_end) - sizeof(uint32_t); + + /* size _lost_ ? */ + //int size = (void*)buf_out + block_size - write_pos + // + sizeof(uint16_t) + sizeof(uint32_t); + g_assert((void*)write_pos < (void*)buf_out + block_size); + write_to_buffer(write_pos,(void*)&end,sizeof(buffer_end)); + write_pos = buf_out + block_size - sizeof(uint32_t); + write_to_buffer(write_pos,(void*)&size, sizeof(uint32_t)); + write(fdCpu,(void*)buf_out, block_size); + + //write out processes and intrrupts files + { + int size_intr = block_size + (void*)buf_intr - write_pos_intr + - sizeof(buffer_end) - sizeof(uint32_t); + int size_proc = block_size + (void*)buf_proc - write_pos_proc + - sizeof(buffer_end) - sizeof(uint32_t); + //int size_intr = block_size - (write_pos_intr - (void*)buf_intr); + //int size_proc = block_size - (write_pos_proc - (void*)buf_proc); + write_to_buffer(write_pos_intr,(void*)&newId,sizeof(uint16_t)); + write_to_buffer(write_pos_intr,(void*)&time_delta, sizeof(uint32_t)); + end_intr = end; + end_intr.nanoseconds -= 20; + write_to_buffer(write_pos_intr,(void*)&end_intr,sizeof(buffer_start)); + + write_to_buffer(write_pos_proc,(void*)&newId,sizeof(uint16_t)); + write_to_buffer(write_pos_proc,(void*)&time_delta, sizeof(uint32_t)); + end_proc = end; + end_proc.nanoseconds -= 40; + write_to_buffer(write_pos_proc,(void*)&end_proc,sizeof(buffer_start)); + + write_pos_intr = buf_intr + block_size - sizeof(uint32_t); + write_pos_proc = buf_proc + block_size - sizeof(uint32_t); + write_to_buffer(write_pos_intr,(void*)&size_intr, sizeof(uint32_t)); + write_to_buffer(write_pos_proc,(void*)&size_proc, sizeof(uint32_t)); + //for now don't output processes and interrupt information + // write(fdIntr,(void*)buf_intr,block_size); + // write(fdProc,(void*)buf_proc,block_size); + } + break; + } + + event_count++; + switch(evId){ + case TRACE_SYSCALL_ENTRY: + event_size = sizeof(trace_syscall_entry); + break; + case TRACE_SYSCALL_EXIT: + event_size = 0; + break; + case TRACE_TRAP_ENTRY: + event_size = sizeof(trace_trap_entry); + break; + case TRACE_TRAP_EXIT: + event_size = 0; + break; + case TRACE_IRQ_ENTRY: + event_size = sizeof(trace_irq_entry); + timeDelta = time_delta; + write_to_buffer(write_pos_intr,(void*)&newId, sizeof(uint16_t)); + write_to_buffer(write_pos_intr,(void*)&timeDelta, sizeof(uint32_t)); + write_to_buffer(write_pos_intr,cur_pos, event_size); + break; + case TRACE_IRQ_EXIT: + event_size = 0; + timeDelta = time_delta; + write_to_buffer(write_pos_intr,(void*)&newId, sizeof(uint16_t)); + write_to_buffer(write_pos_intr,(void*)&timeDelta, sizeof(uint32_t)); + break; + case TRACE_SCHEDCHANGE: + event_size = sizeof(trace_schedchange); + break; + case TRACE_KERNEL_TIMER: + event_size = 0; + break; + case TRACE_SOFT_IRQ: + event_size = sizeof(trace_soft_irq); + // timeDelta = time_delta; + // write_to_buffer(write_pos_intr,(void*)&newId, sizeof(uint16_t)); + // write_to_buffer(write_pos_intr,(void*)&timeDelta, sizeof(uint32_t)); + // write_to_buffer(write_pos_intr,cur_pos, event_size); + break; + case TRACE_PROCESS: + event_size = sizeof(trace_process); + timeDelta = time_delta; + subId = *(uint8_t*)cur_pos; + if(subId == TRACE_PROCESS_FORK || subId ==TRACE_PROCESS_EXIT){ + if( subId == TRACE_PROCESS_FORK)tmpId = PROCESS_FORK_ID; + else tmpId = PROCESS_EXIT_ID; + write_to_buffer(write_pos_proc,(void*)&tmpId, sizeof(uint16_t)); + write_to_buffer(write_pos_proc,(void*)&timeDelta, sizeof(uint32_t)); + + process = *(new_process*)(cur_pos + sizeof(uint8_t)); + write_to_buffer(write_pos_proc,(void*)&process, sizeof(new_process)); + } + break; + case TRACE_FILE_SYSTEM: + event_size = sizeof(trace_file_system)- sizeof(char*); + break; + case TRACE_TIMER: + event_size = sizeof(trace_timer); + break; + case TRACE_MEMORY: + event_size = sizeof(trace_memory); + break; + case TRACE_SOCKET: + event_size = sizeof(trace_socket); + break; + case TRACE_IPC: + event_size = sizeof(trace_ipc); + break; + case TRACE_NETWORK: + event_size = sizeof(trace_network); + break; + case TRACE_HEARTBEAT: + beat.seconds = 0; + beat.nanoseconds = 0; + beat.cycle_count = adaptation_tsc; + event_size = 0; + + write_to_buffer(write_pos_intr,(void*)&newId, sizeof(uint16_t)); + write_to_buffer(write_pos_intr,(void*)&time_delta, sizeof(uint32_t)); + write_to_buffer(write_pos_intr,(void*)&beat, sizeof(heartbeat)); + write_to_buffer(write_pos_proc,(void*)&newId, sizeof(uint16_t)); + write_to_buffer(write_pos_proc,(void*)&time_delta, sizeof(uint32_t)); + write_to_buffer(write_pos_proc,(void*)&beat, sizeof(heartbeat)); + break; + default: + event_size = -1; + break; + } + if(evId != TRACE_FILE_SYSTEM && event_size >=0){ + write_to_buffer(write_pos, cur_pos, event_size); + + if(evId == TRACE_HEARTBEAT){ + write_to_buffer(write_pos, (void*)&beat, sizeof(heartbeat)); + } + + cur_pos += event_size + sizeof(uint16_t); //skip data_size + }else if(evId == TRACE_FILE_SYSTEM){ + size_t nbBytes; + char c = '\0'; + tFileSys = (trace_file_system*)cur_pos; + subId = tFileSys->event_sub_id; + if(subId == TRACE_FILE_SYSTEM_OPEN || subId == TRACE_FILE_SYSTEM_EXEC){ + nbBytes = tFileSys->event_data2 +1; + }else nbBytes = 0; + + write_to_buffer(write_pos, cur_pos, event_size); + cur_pos += event_size + sizeof(char*); + if(nbBytes){ + write_to_buffer(write_pos, cur_pos, nbBytes); + }else{ + write_to_buffer(write_pos, (void*)&c, 1); + } + cur_pos += nbBytes + sizeof(uint16_t); //skip data_size + }else if(event_size == -1){ + printf("Unknown event: evId=%d, i=%d, event_count=%d\n", newId, i, event_count); + exit(1); + } + } //end while(1) + } + close(fd); + close(fdCpu); + g_free(buffer); + buffer = NULL; + g_free(buf_fac); + g_free(buf_intr); + g_free(buf_proc); + g_free(buf_out); + } + + + + + + //write to system.xml + fprintf(fp,"\n"); + fprintf(fp,"This is just a test\n"); + fprintf(fp,"\n"); + fflush(fp); + + close(fdFac); + close(fdIntr); + close(fdProc); + fclose(fp); + + g_printf("Conversion completed. Don't forget to copy core.xml to eventdefs directory\n"); + + return 0; +} + diff --git a/ltt/branches/poly/ltt-newlib/convert/core.xml b/ltt/branches/poly/ltt-newlib/convert/core.xml new file mode 100644 index 00000000..b1b23d61 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/convert/core.xml @@ -0,0 +1,263 @@ + + The core facility contains the basic events + + + Facility used in the trace + + + + + + + + + Entry in a given system call + + Syscall entry number in entry.S + Address from which call was made + + + + + Exit from a given system call + + + + Entry in a trap + + Trap number + Address where trap occured + + + + + Exit from a trap + + + + Entry in an irq + + IRQ number + Are we executing kernel code + + + + + Exit from an IRQ + + + + Scheduling change + + Outgoing process + Incoming process + Outgoing process' state + + + + + The kernel timer routine has been called + + + + Hit key part of soft-irq management + + Soft-irq event Id + + + + + Data associated with event + + + + + Hit key part of process management + + Process event ID + + + + + Data associated with event + Data associated with event + + + + + Hit key part of file system + + File system event ID + + + + + Event data + Event data 2 + Name of file operated on + + + + + Hit key part of timer management + + Timer event ID + + + + + Short data + Data associated with event + Data associated with event + + + + + Hit key part of memory management + + Memory event ID + + + + + Data associated with event + + + + + Hit key part of socket communication + + Memory event ID + + + + + Data associated with event + Data associated with event + + + + + Hit key part of System V IPC + + Memory event ID + + + + + Data associated with event + Data associated with event + + + + + Hit key part of network communication + + Memory event ID + + + + + Data associated with event + + + + + Block start timestamp + + + + + Block end timestamp + + + + + System time values sent periodically to minimize cycle counter + drift with respect to real time clock and to detect cycle counter roolovers + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fork a new process + + Data associated with event + Data associated with event + + + + + Exit from a process + + Data associated with event + Data associated with event + + + + + + diff --git a/ltt/branches/poly/ltt-newlib/convert/sysInfo b/ltt/branches/poly/ltt-newlib/convert/sysInfo new file mode 100755 index 00000000..fdd7b596 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/convert/sysInfo @@ -0,0 +1,45 @@ +#!/bin/bash + +# DO NOT FORGET TO DISABLE ALL THE JAVA OPTIONS IN NETSCAPE +# OTHERWISE IT WILL DIE ... + +outputFile=sysInfo.out + +NODE_NAME=`uname -n` +echo "node_name="$NODE_NAME > $outputFile + +DOMAINNAME="`hostname --domain`" +echo "domainname="$DOMAINNAME >> $outputFile + +KERNEL_NAME="`uname -s`" +echo "kernel_name="$KERNEL_NAME >> $outputFile + +KERNEL_RELEASE="`uname -r`" +echo "kernel_release="$KERNEL_RELEASE >> $outputFile + +KERNEL_VERSION="`uname -v`" +echo "kernel_version="$KERNEL_VERSION >> $outputFile + +MACHINE="`uname -m`" +echo "machine="$MACHINE >> $outputFile + + +# not available anymore in uname version 5 and newer +PROCESSOR="`uname -p`" +echo "processor="$PROCESSOR >> $outputFile + +# not available anymore in uname version 5 and newer +HARDWARE_PLATFORM="`uname -i`" +echo "hardware_platform="$HARDWARE_PLATFORM >> $outputFile + +OPERATING_SYSTEM="`uname -o`" +echo "operating_system="$OPERATING_SYSTEM >> $outputFile + + +#export $NODE_NAME +#export $NODE_NAME $DOMAINNAME $KERNEL_NAME $KERNEL_RELEASE $KERNEL_VERSION $MACHINE $PROCESSOR $HARDWARE_PLATFORM $OPERATING_SYSTEM + + + +#/sbin/lilo -C "$liloConf" + diff --git a/ltt/branches/poly/ltt-newlib/crc32.tab b/ltt/branches/poly/ltt-newlib/crc32.tab new file mode 100644 index 00000000..d0174ad6 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/crc32.tab @@ -0,0 +1,52 @@ + 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, + 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, + 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, + 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, + 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, + 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, + 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, + 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, + 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, + 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU, + 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, + 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, + 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, + 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, + 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, + 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, + 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, + 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, + 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, + 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, + 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, + 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, + 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, + 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, + 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, + 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, + 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, + 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, + 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, + 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, + 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, + 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, + 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, + 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU, + 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, + 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, + 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, + 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, + 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, + 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, + 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, + 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, + 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, + 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, + 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, + 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, + 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, + 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, + 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, + 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, + 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, + 0x2d02ef8dU diff --git a/ltt/branches/poly/ltt-newlib/event.c b/ltt/branches/poly/ltt-newlib/event.c new file mode 100644 index 00000000..02ecf271 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/event.c @@ -0,0 +1,709 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2003-2004 Xiangxiu Yang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#include "parser.h" +#include +#include "ltt-private.h" +#include +#include +#include + + +LttEvent *ltt_event_new() +{ + return g_new(LttEvent, 1); +} + +void ltt_event_destroy(LttEvent *event) +{ + g_free(event); +} + + +/***************************************************************************** + *Function name + * ltt_event_refresh_fields : refresh fields of an event + *Input params + * offsetRoot : offset from the root + * offsetParent : offset from the parent + * fld : field + * evD : event data + * reverse_byte_order : 1 or 0 + *Return value + * int : size of the field + ****************************************************************************/ + +int ltt_event_refresh_fields(int offsetRoot,int offsetParent, + LttField * fld, void *evD, gboolean reverse_byte_order) +{ + int size, size1, element_number, i, offset1, offset2; + LttType * type = fld->field_type; + + switch(type->type_class) { + case LTT_ARRAY: + element_number = (int) type->element_number; + if(fld->field_fixed == 0){// has string or sequence + size = 0; + for(i=0;ichild[0], evD+size, reverse_byte_order); + } + }else size = fld->field_size; + break; + + case LTT_SEQUENCE: + size1 = fld->sequ_number_size; + element_number = getIntNumber(reverse_byte_order,size1,evD); + type->element_number = element_number; + if(fld->element_size > 0){ + size = element_number * fld->element_size; + }else{//sequence has string or sequence + size = 0; + for(i=0;ichild[0], evD+size+size1, reverse_byte_order); + } + size += size1; + } + break; + + case LTT_STRING: + size = strlen((gchar*)evD) + 1; //include end : '\0' + break; + + case LTT_STRUCT: + element_number = (int) type->element_number; + if(fld->field_fixed == 0){ + offset1 = offsetRoot; + offset2 = 0; + for(i=0;ichild[i],evD+offset2, reverse_byte_order); + offset1 += size; + offset2 += size; + } + size = offset2; + }else size = fld->field_size; + break; + + case LTT_UNION: + size = fld->field_size; + break; + + default: + size = fld->field_size; + } + +#if 0 + if(type->type_class != LTT_STRUCT && type->type_class != LTT_ARRAY && + type->type_class != LTT_SEQUENCE && type->type_class != LTT_STRING){ + size = fld->field_size; + }else if(type->type_class == LTT_ARRAY){ + element_number = (int) type->element_number; + if(fld->field_fixed == 0){// has string or sequence + size = 0; + for(i=0;ichild[0], evD+size); + } + }else size = fld->field_size; + }else if(type->type_class == LTT_SEQUENCE){ + size1 = fld->sequ_number_size; + element_number = getIntNumber(size1,evD); + type->element_number = element_number; + if(fld->element_size > 0){ + size = element_number * fld->element_size; + }else{//sequence has string or sequence + size = 0; + for(i=0;ichild[0], evD+size+size1); + } + size += size1; + } + }else if(type->type_class == LTT_STRING){ + size = strlen((char*)evD) + 1; //include end : '\0' + }else if(type->type_class == LTT_STRUCT){ + element_number = (int) type->element_number; + if(fld->field_fixed == 0){ + offset1 = offsetRoot; + offset2 = 0; + for(i=0;ichild[i],evD+offset2); + offset1 += size; + offset2 += size; + } + size = offset2; + }else size = fld->field_size; + } +#endif //0 + fld->offset_root = offsetRoot; + fld->offset_parent = offsetParent; + fld->fixed_root = (offsetRoot==-1) ? 0 : 1; + fld->fixed_parent = (offsetParent==-1) ? 0 : 1; + fld->field_size = size; + + return size; +} + +/***************************************************************************** + *Function name + * ltt_event_eventtype_id: get event type id + * (base id + position of the event) + *Input params + * e : an instance of an event type + *Return value + * unsigned : event type id + ****************************************************************************/ + +unsigned ltt_event_eventtype_id(LttEvent *e) +{ + return (unsigned) e->event_id; +} + +/***************************************************************************** + *Function name + * ltt_event_facility : get the facility of the event + *Input params + * e : an instance of an event type + *Return value + * LttFacility * : the facility of the event + ****************************************************************************/ + +LttFacility *ltt_event_facility(LttEvent *e) +{ + LttTrace * trace = e->tracefile->trace; + unsigned id = e->event_id; + return ltt_trace_facility_by_id(trace,id); +} + +/***************************************************************************** + *Function name + * ltt_event_eventtype : get the event type of the event + *Input params + * e : an instance of an event type + *Return value + * LttEventType * : the event type of the event + ****************************************************************************/ + +LttEventType *ltt_event_eventtype(LttEvent *e) +{ + LttFacility* facility = ltt_event_facility(e); + if(!facility) return NULL; + return facility->events[e->event_id - facility->base_id]; +} + +/***************************************************************************** + *Function name + * ltt_event_field : get the root field of the event + *Input params + * e : an instance of an event type + *Return value + * LttField * : the root field of the event + ****************************************************************************/ + +LttField *ltt_event_field(LttEvent *e) +{ + LttField * field; + LttEventType * event_type = ltt_event_eventtype(e); + if(unlikely(!event_type)) return NULL; + field = event_type->root_field; + if(unlikely(!field)) return NULL; + + //check if the field need refresh + if(likely(e->which_block != event_type->latest_block || + e->which_event != event_type->latest_event)){ + + event_type->latest_block = e->which_block; + event_type->latest_event = e->which_event; + + if(unlikely(field->field_fixed != 1)) + ltt_event_refresh_fields(0, 0, field, e->data, + e->tracefile->trace->reverse_byte_order); + } + return field; +} + +/***************************************************************************** + *Function name + * ltt_event_time : get the time of the event + *Input params + * e : an instance of an event type + *Return value + * LttTime : the time of the event + ****************************************************************************/ + +LttTime ltt_event_time(LttEvent *e) +{ + return e->event_time; +} + +/***************************************************************************** + *Function name + * ltt_event_time : get the cycle count of the event + *Input params + * e : an instance of an event type + *Return value + * LttCycleCount : the cycle count of the event + ****************************************************************************/ + +LttCycleCount ltt_event_cycle_count(LttEvent *e) +{ + return e->event_cycle_count; +} + +/***************************************************************************** + *Function name + * ltt_event_position : get the event's position + *Input params + * e : an instance of an event type + * ep : a pointer to event's position structure + ****************************************************************************/ + +void ltt_event_position(LttEvent *e, LttEventPosition *ep) +{ + ep->block_num = e->which_block; + ep->event_num = e->which_event; + ep->event_time = e->event_time; + ep->event_cycle_count = e->event_cycle_count; + ep->heart_beat_number = e->tracefile->cur_heart_beat_number; + ep->old_position = TRUE; + ep->event_offset = e->data - e->tracefile->buffer - EVENT_HEADER_SIZE ; + ep->tf = e->tracefile; + ep->overflow_nsec = e->overflow_nsec; + /* This is a workaround for fast position seek */ + ep->last_event_pos = e->last_event_pos; + ep->prev_block_end_time = e->prev_block_end_time; + ep->prev_event_time = e->prev_event_time; + ep->pre_cycle_count = e->pre_cycle_count; + ep->count = e->count; + ep->last_heartbeat = e->last_heartbeat; + + /* end of workaround */ +} + +LttEventPosition * ltt_event_position_new() +{ + return g_new(LttEventPosition, 1); +} + +/***************************************************************************** + *Function name + * ltt_event_position_get : get the block number and index of the event + *Input params + * ep : a pointer to event's position structure + * block_number : the block number of the event + * index_in_block : the index of the event within the block + ****************************************************************************/ + +void ltt_event_position_get(LttEventPosition *ep, + unsigned *block_number, unsigned *index_in_block, LttTracefile ** tf) +{ + *block_number = ep->block_num; + *index_in_block = ep->event_num; + *tf = ep->tf; +} + +/***************************************************************************** + *Function name + * ltt_event_position_set : set the block number and index of the event + * It does put the old_position gboolean to FALSE, as it is impossible + * to know the quick position to seek in the tracefile. + *Input params + * ep : a pointer to event's position structure + * block_number : the block number of the event + * index_in_block : the index of the event within the block + ****************************************************************************/ + +void ltt_event_position_set(LttEventPosition *ep, + unsigned block_number, unsigned index_in_block) +{ + if(ep->block_num != block_number || ep->event_num != index_in_block) + ep->old_position = FALSE; + + ep->block_num = block_number; + ep->event_num = index_in_block; + +} + +/***************************************************************************** + * Function name + * ltt_event_position_compare : compare two positions + * A NULL value is infinite. + * Input params + * ep1 : a pointer to event's position structure + * ep2 : a pointer to event's position structure + * Return + * -1 is ep1 < ep2 + * 1 if ep1 > ep2 + * 0 if ep1 == ep2 + ****************************************************************************/ + + +gint ltt_event_position_compare(const LttEventPosition *ep1, + const LttEventPosition *ep2) +{ + if(ep1->tf != ep2->tf) + g_error("ltt_event_position_compare on different tracefiles makes no sense"); + if(ep1 == NULL && ep2 == NULL) + return 0; + if(ep1 != NULL && ep2 == NULL) + return -1; + if(ep1 == NULL && ep2 != NULL) + return 1; + + if(ep1->block_num < ep2->block_num) + return -1; + if(ep1->block_num > ep2->block_num) + return 1; + if(ep1->event_num < ep2->event_num) + return -1; + if(ep1->event_num > ep2->event_num) + return 1; + return 0; +} + +/***************************************************************************** + * Function name + * ltt_event_event_position_compare : compare two positions, one in event, + * other in position opaque structure. + * Input params + * event : a pointer to event structure + * ep : a pointer to event's position structure + * Return + * -1 is event < ep + * 1 if event > ep + * 0 if event == ep + ****************************************************************************/ + +gint ltt_event_event_position_compare(const LttEvent *event, + const LttEventPosition *ep) +{ + if(event == NULL && ep == NULL) + return 0; + if(event != NULL && ep == NULL) + return -1; + if(event == NULL && ep != NULL) + return 1; + + g_assert(event->tracefile == ep->tf); + + if(event->which_block < ep->block_num) + return -1; + if(event->which_block > ep->block_num) + return 1; + if(event->which_event < ep->event_num) + return -1; + if(event->which_event > ep->event_num) + return 1; + return 0; +} + +/***************************************************************************** + * Function name + * ltt_event_position_copy : copy position + * Input params + * src : a pointer to event's position structure source + * dest : a pointer to event's position structure dest + * Return + * void + ****************************************************************************/ +void ltt_event_position_copy(LttEventPosition *dest, + const LttEventPosition *src) +{ + if(src == NULL) + dest = NULL; + else + *dest = *src; +} + + +/***************************************************************************** + *Function name + * ltt_event_cpu_i: get the cpu id where the event happens + *Input params + * e : an instance of an event type + *Return value + * unsigned : the cpu id + ****************************************************************************/ + +unsigned ltt_event_cpu_id(LttEvent *e) +{ + gchar * c1, * c2, * c3; + c1 = strrchr(e->tracefile->name,'\\'); + c2 = strrchr(e->tracefile->name,'/'); + if(c1 == NULL && c2 == NULL){ + return (unsigned)atoi(e->tracefile->name); + }else if(c1 == NULL){ + c2++; + return (unsigned)atoi(c2); + }else if(c2 == NULL){ + c1++; + return (unsigned)atoi(c1); + }else{ + c3 = (c1 > c2) ? c1 : c2; + c3++; + return (unsigned)atoi(c3); + } +} + +/***************************************************************************** + *Function name + * ltt_event_data : get the raw data for the event + *Input params + * e : an instance of an event type + *Return value + * void * : pointer to the raw data for the event + ****************************************************************************/ + +void *ltt_event_data(LttEvent *e) +{ + return e->data; +} + +/***************************************************************************** + *Function name + * ltt_event_field_element_number + * : The number of elements in a sequence field is specific + * to each event. This function returns the number of + * elements for an array or sequence field in an event. + *Input params + * e : an instance of an event type + * f : a field of the instance + *Return value + * unsigned : the number of elements for an array/sequence field + ****************************************************************************/ + +unsigned ltt_event_field_element_number(LttEvent *e, LttField *f) +{ + if(f->field_type->type_class != LTT_ARRAY && + f->field_type->type_class != LTT_SEQUENCE) + return 0; + + if(f->field_type->type_class == LTT_ARRAY) + return f->field_type->element_number; + return (unsigned) getIntNumber(e->tracefile->trace->reverse_byte_order, + f->sequ_number_size, e + f->offset_root); +} + +/***************************************************************************** + *Function name + * ltt_event_field_element_select + * : Set the currently selected element for a sequence or + * array field + *Input params + * e : an instance of an event type + * f : a field of the instance + * i : the ith element + ****************************************************************************/ + +void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i) +{ + unsigned element_number; + LttField *fld; + unsigned int k; + int size; + void *evD; + + if(f->field_type->type_class != LTT_ARRAY && + f->field_type->type_class != LTT_SEQUENCE) + return ; + + element_number = ltt_event_field_element_number(e,f); + /* Sanity check for i : 1..n only, and must be lower or equal element_number + */ + if(element_number < i || i == 0) return; + + fld = f->child[0]; + + evD = e->data + f->offset_root; + size = 0; + for(k=0;koffset_root+size,size, fld, evD+size, + e->tracefile->trace->reverse_byte_order); + } + f->current_element = i - 1; +} + +/***************************************************************************** + * These functions extract data from an event after architecture specific + * conversions + ****************************************************************************/ + +guint32 ltt_event_get_unsigned(LttEvent *e, LttField *f) +{ + //int revFlag = e->tracefile->trace->my_arch_endian == + // e->tracefile->trace->system_description->endian ? 0:1; + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; + + LttTypeEnum t = f->field_type->type_class; + + g_assert(t == LTT_UINT || t == LTT_ENUM); + + if(f->field_size == 1){ + guint8 x = *(guint8 *)(e->data + f->offset_root); + return (guint32) x; + }else if(f->field_size == 2){ + return (guint32)ltt_get_uint16(reverse_byte_order, e->data + f->offset_root); + }else if(f->field_size == 4){ + return (guint32)ltt_get_uint32(reverse_byte_order, e->data + f->offset_root); + } +#if 0 + else if(f->field_size == 8){ + guint64 x = *(guint64 *)(e->data + f->offset_root); + if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN) + return (unsigned int) (revFlag ? GUINT64_FROM_BE(x): x); + else + return (unsigned int) (revFlag ? GUINT64_FROM_LE(x): x); + } +#endif //0 + g_critical("ltt_event_get_unsigned : field size %i unknown", f->field_size); + return 0; +} + +gint32 ltt_event_get_int(LttEvent *e, LttField *f) +{ + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; + //int revFlag = e->tracefile->trace->my_arch_endian == + // e->tracefile->trace->system_description->endian ? 0:1; + + g_assert(f->field_type->type_class == LTT_INT); + + if(f->field_size == 1){ + gint8 x = *(gint8 *)(e->data + f->offset_root); + return (gint32) x; + }else if(f->field_size == 2){ + return (gint32)ltt_get_int16(reverse_byte_order, e->data + f->offset_root); + }else if(f->field_size == 4){ + return (gint32)ltt_get_int32(reverse_byte_order, e->data + f->offset_root); + } +#if 0 + else if(f->field_size == 8){ + gint64 x = *(gint64 *)(e->data + f->offset_root); + if(e->tracefile->trace->my_arch_endian == LTT_LITTLE_ENDIAN) + return (int) (revFlag ? GINT64_FROM_BE(x): x); + else + return (int) (revFlag ? GINT64_FROM_LE(x): x); + } +#endif //0 + g_critical("ltt_event_get_int : field size %i unknown", f->field_size); + return 0; +} + +guint64 ltt_event_get_long_unsigned(LttEvent *e, LttField *f) +{ + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; + //int revFlag = e->tracefile->trace->my_arch_endian == + // e->tracefile->trace->system_description->endian ? 0:1; + LttTypeEnum t = f->field_type->type_class; + + g_assert(t == LTT_UINT || t == LTT_ENUM); + + if(f->field_size == 1){ + guint8 x = *(guint8 *)(e->data + f->offset_root); + return (guint64) x; + }else if(f->field_size == 2){ + return (guint64)ltt_get_uint16(reverse_byte_order, e->data + f->offset_root); + }else if(f->field_size == 4){ + return (guint64)ltt_get_uint32(reverse_byte_order, e->data + f->offset_root); + }else if(f->field_size == 8){ + return ltt_get_uint64(reverse_byte_order, e->data + f->offset_root); + } + g_critical("ltt_event_get_long_unsigned : field size %i unknown", f->field_size); + return 0; +} + +gint64 ltt_event_get_long_int(LttEvent *e, LttField *f) +{ + //int revFlag = e->tracefile->trace->my_arch_endian == + // e->tracefile->trace->system_description->endian ? 0:1; + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; + + g_assert( f->field_type->type_class == LTT_INT); + + if(f->field_size == 1){ + gint8 x = *(gint8 *)(e->data + f->offset_root); + return (gint64) x; + }else if(f->field_size == 2){ + return (gint64)ltt_get_int16(reverse_byte_order, e->data + f->offset_root); + }else if(f->field_size == 4){ + return (gint64)ltt_get_int32(reverse_byte_order, e->data + f->offset_root); + }else if(f->field_size == 8){ + return ltt_get_int64(reverse_byte_order, e->data + f->offset_root); + } + g_critical("ltt_event_get_long_int : field size %i unknown", f->field_size); + return 0; +} + +float ltt_event_get_float(LttEvent *e, LttField *f) +{ + //int revFlag = e->tracefile->trace->my_arch_endian == + // e->tracefile->trace->system_description->endian ? 0:1; + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; + + g_assert(f->field_type->type_class == LTT_FLOAT && f->field_size == 4); + + if(reverse_byte_order == 0) return *(float *)(e->data + f->offset_root); + else{ + guint32 aInt; + memcpy((void*)&aInt, e->data + f->offset_root, 4); + aInt = ___swab32(aInt); + return ((float)aInt); + } +} + +double ltt_event_get_double(LttEvent *e, LttField *f) +{ + gboolean reverse_byte_order = e->tracefile->trace->reverse_byte_order; + //int revFlag = e->tracefile->trace->my_arch_endian == + // e->tracefile->trace->system_description->endian ? 0:1; + + g_assert(f->field_type->type_class == LTT_FLOAT && f->field_size == 8); + + if(reverse_byte_order == 0) return *(double *)(e->data + f->offset_root); + else{ + guint64 aInt; + memcpy((void*)&aInt, e->data + f->offset_root, 8); + aInt = ___swab64(aInt); + return ((double)aInt); + } +} + +/***************************************************************************** + * The string obtained is only valid until the next read from + * the same tracefile. + ****************************************************************************/ + +char *ltt_event_get_string(LttEvent *e, LttField *f) +{ + g_assert(f->field_type->type_class == LTT_STRING); + + return (gchar*)g_strdup((gchar*)(e->data + f->offset_root)); +} diff --git a/ltt/branches/poly/ltt-newlib/event.h b/ltt/branches/poly/ltt-newlib/event.h new file mode 100644 index 00000000..3f1f8972 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/event.h @@ -0,0 +1,135 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Michel Dagenais + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef EVENT_H +#define EVENT_H + +#include + +LttEvent *ltt_event_new(); + +void ltt_event_destroy(LttEvent *event); + +/* Events and their content, including the raw data, are only valid + until reading another event from the same tracefile. + Indeed, since event reading is critical to the performance, + the memory associated with an event may be reused at each read. */ + +/* Obtain the trace unique integer id associated with the type of + this event */ + +unsigned ltt_event_eventtype_id(LttEvent *e); + + +/* Facility and type for the event */ + +LttFacility *ltt_event_facility(LttEvent *e); + +LttEventType *ltt_event_eventtype(LttEvent *e); + + +/* Root field for the event */ + +LttField *ltt_event_field(LttEvent *e); + + +/* Time and cycle count for the event */ + +LttTime ltt_event_time(LttEvent *e); + +LttCycleCount ltt_event_cycle_count(LttEvent *e); + + +/* Obtain the position of the event within the tracefile. This + is used to seek back to this position later or to seek to another + position, computed relative to this position. The event position + structure is opaque and contains several fields, only two + of which are user accessible: block number and event index + within the block. */ + +void ltt_event_position(LttEvent *e, LttEventPosition *ep); + +LttEventPosition * ltt_event_position_new(); + +void ltt_event_position_get(LttEventPosition *ep, + unsigned *block_number, unsigned *index_in_block, LttTracefile ** tf); + +void ltt_event_position_set(LttEventPosition *ep, + unsigned block_number, unsigned index_in_block); + +gint ltt_event_position_compare(const LttEventPosition *ep1, + const LttEventPosition *ep2); + +gint ltt_event_event_position_compare(const LttEvent *event, + const LttEventPosition *ep); + +void ltt_event_position_copy(LttEventPosition *dest, + const LttEventPosition *src); + +/* CPU id of the event */ + +unsigned ltt_event_cpu_id(LttEvent *e); + + +/* Pointer to the raw data for the event. This should not be used directly + unless prepared to do all the architecture specific conversions. */ + +void *ltt_event_data(LttEvent *e); + + +/* The number of elements in a sequence field is specific to each event + instance. This function returns the number of elements for an array or + sequence field in an event. */ + +unsigned ltt_event_field_element_number(LttEvent *e, LttField *f); + + +/* Set the currently selected element for a sequence or array field. */ + +void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i); + + +/* A union is like a structure except that only a single member at a time + is present depending on the specific event instance. This function tells + the active member for a union field in an event. */ + +unsigned ltt_event_field_union_member(LttEvent *e, LttField *f); + + +/* These functions extract data from an event after architecture specific + conversions. */ + +guint32 ltt_event_get_unsigned(LttEvent *e, LttField *f); + +gint32 ltt_event_get_int(LttEvent *e, LttField *f); + +guint64 ltt_event_get_long_unsigned(LttEvent *e, LttField *f); + +gint64 ltt_event_get_long_int(LttEvent *e, LttField *f); + +float ltt_event_get_float(LttEvent *e, LttField *f); + +double ltt_event_get_double(LttEvent *e, LttField *f); + + +/* The string obtained is only valid until the next read from + the same tracefile. */ + +gchar *ltt_event_get_string(LttEvent *e, LttField *f); + +#endif // EVENT_H diff --git a/ltt/branches/poly/ltt-newlib/facility.c b/ltt/branches/poly/ltt-newlib/facility.c new file mode 100644 index 00000000..84baac98 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/facility.c @@ -0,0 +1,568 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2003-2004 Xiangxiu Yang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + + + +#include "parser.h" +#include +#include "ltt-private.h" +#include + +#ifndef g_open +#define g_open open +#endif + +#define g_close close + +/* search for the (named) type in the table, if it does not exist + create a new one */ +LttType * lookup_named_type(LttFacility *fac, type_descriptor * td); + +/* construct directed acyclic graph for types, and tree for fields */ +void constructTypeAndFields(LttFacility * fac,type_descriptor * td, + LttField * fld); + +/* generate the facility according to the events belongin to it */ +void generateFacility(LttFacility * f, facility_t * fac, + LttChecksum checksum); + +/* functions to release the memory occupied by a facility */ +void freeFacility(LttFacility * facility); +void freeEventtype(LttEventType * evType); +void freeLttType(LttType ** type); +void freeLttField(LttField * fld); +void freeLttNamedType(LttType * type); + + +/***************************************************************************** + *Function name + * ltt_facility_open : open facilities + *Input params + * t : the trace containing the facilities + * pathname : the path name of the facility + ****************************************************************************/ + +void ltt_facility_open(LttTrace * t, gchar * pathname) +{ + gchar *token; + parse_file in; + gsize length; + facility_t * fac; + LttFacility * f; + LttChecksum checksum; + GError * error = NULL; + gchar buffer[BUFFER_SIZE]; + + in.buffer = &(buffer[0]); + in.lineno = 0; + in.error = error_callback; + in.name = pathname; + + in.fd = g_open(in.name, O_RDONLY, 0); + if(in.fd < 0 ) in.error(&in,"cannot open input file"); + + in.channel = g_io_channel_unix_new(in.fd); + in.pos = 0; + + while(1){ + token = getToken(&in); + if(in.type == ENDFILE) break; + + if(g_ascii_strcasecmp(token, "<")) in.error(&in,"not a facility file"); + token = getName(&in); + + if(g_ascii_strcasecmp("facility",token) == 0) { + fac = g_new(facility_t, 1); + fac->name = NULL; + fac->description = NULL; + sequence_init(&(fac->events)); + table_init(&(fac->named_types)); + sequence_init(&(fac->unnamed_types)); + + parseFacility(&in, fac); + + //check if any namedType is not defined + g_assert(checkNamedTypesImplemented(&fac->named_types) == 0); + + g_assert(generateChecksum(fac->name, &checksum, &fac->events) == 0); + + f = g_new(LttFacility,1); + f->base_id = 0; + generateFacility(f, fac, checksum); + + t->facility_number++; + g_ptr_array_add(t->facilities,f); + + g_free(fac->name); + g_free(fac->description); + freeEvents(&fac->events); + sequence_dispose(&fac->events); + freeNamedType(&fac->named_types); + table_dispose(&fac->named_types); + freeTypes(&fac->unnamed_types); + sequence_dispose(&fac->unnamed_types); + g_free(fac); + } + else in.error(&in,"facility token was expected"); + } + + g_io_channel_shutdown(in.channel, FALSE, &error); /* No flush */ + if(error != NULL) { + g_warning("Can not close file: \n%s\n", error->message); + g_error_free(error); + } + + g_close(in.fd); +} + + +/***************************************************************************** + *Function name + * generateFacility : generate facility, internal function + *Input params + * facility : LttFacilty structure + * fac : facility structure + * checksum : checksum of the facility + ****************************************************************************/ + +void generateFacility(LttFacility *f, facility_t *fac,LttChecksum checksum) +{ + char * facilityName = fac->name; + sequence * events = &fac->events; + int i; + LttEventType * evType; + LttField * field; + LttType * type; + + f->name = g_strdup(facilityName); + f->event_number = events->position; + f->checksum = checksum; + + //initialize inner structures + f->events = g_new(LttEventType*,f->event_number); + f->named_types_number = fac->named_types.keys.position; + f->named_types = g_new(LttType*, fac->named_types.keys.position); + for(i=0;inamed_types.keys.position;i++) f->named_types[i] = NULL; + + //for each event, construct field tree and type graph + for(i=0;iposition;i++){ + evType = g_new(LttEventType,1); + f->events[i] = evType; + + evType->name = g_strdup(((event_t*)(events->array[i]))->name); + evType->description=g_strdup(((event_t*)(events->array[i]))->description); + + field = g_new(LttField, 1); + evType->root_field = field; + evType->facility = f; + evType->index = i; + + if(((event_t*)(events->array[i]))->type != NULL){ + field->field_pos = 0; + type = lookup_named_type(f,((event_t*)(events->array[i]))->type); + field->field_type = type; + field->offset_root = 0; + field->fixed_root = 1; + field->offset_parent = 0; + field->fixed_parent = 1; + // field->base_address = NULL; + field->field_size = 0; + field->field_fixed = -1; + field->parent = NULL; + field->child = NULL; + field->current_element = 0; + + //construct field tree and type graph + constructTypeAndFields(f,((event_t*)(events->array[i]))->type,field); + }else{ + evType->root_field = NULL; + g_free(field); + } + } +} + + +/***************************************************************************** + *Function name + * constructTypeAndFields : construct field tree and type graph, + * internal recursion function + *Input params + * fac : facility struct + * td : type descriptor + * root_field : root field of the event + ****************************************************************************/ + +void constructTypeAndFields(LttFacility * fac,type_descriptor * td, + LttField * fld) +{ + int i, flag; + type_descriptor * tmpTd; + + // if(td->type == LTT_STRING || td->type == LTT_SEQUENCE) + // fld->field_size = 0; + // else fld->field_size = -1; + + if(td->type == LTT_ENUM){ + fld->field_type->element_number = td->labels.position; + fld->field_type->enum_strings = g_new(char*,td->labels.position); + for(i=0;ilabels.position;i++){ + fld->field_type->enum_strings[i] + = g_strdup(((char*)(td->labels.array[i]))); + } + }else if(td->type == LTT_ARRAY || td->type == LTT_SEQUENCE){ + if(td->type == LTT_ARRAY) + fld->field_type->element_number = (unsigned)td->size; + fld->field_type->element_type = g_new(LttType*,1); + tmpTd = td->nested_type; + fld->field_type->element_type[0] = lookup_named_type(fac, tmpTd); + fld->child = g_new(LttField*, 1); + fld->child[0] = g_new(LttField, 1); + + fld->child[0]->field_pos = 0; + fld->child[0]->field_type = fld->field_type->element_type[0]; + fld->child[0]->offset_root = fld->offset_root; + fld->child[0]->fixed_root = fld->fixed_root; + fld->child[0]->offset_parent = 0; + fld->child[0]->fixed_parent = 1; + // fld->child[0]->base_address = NULL; + fld->child[0]->field_size = 0; + fld->child[0]->field_fixed = -1; + fld->child[0]->parent = fld; + fld->child[0]->child = NULL; + fld->child[0]->current_element = 0; + constructTypeAndFields(fac, tmpTd, fld->child[0]); + }else if(td->type == LTT_STRUCT){ + fld->field_type->element_number = td->fields.position; + + if(fld->field_type->element_type == NULL){ + fld->field_type->element_type = g_new(LttType*, td->fields.position); + flag = 1; + }else{ + flag = 0; + } + + fld->child = g_new(LttField*, td->fields.position); + for(i=0;ifields.position;i++){ + tmpTd = ((type_fields*)(td->fields.array[i]))->type; + + if(flag) + fld->field_type->element_type[i] = lookup_named_type(fac, tmpTd); + fld->child[i] = g_new(LttField,1); + + fld->child[i]->field_pos = i; + fld->child[i]->field_type = fld->field_type->element_type[i]; + + if(flag){ + fld->child[i]->field_type->element_name + = g_strdup(((type_fields*)(td->fields.array[i]))->name); + } + + fld->child[i]->offset_root = -1; + fld->child[i]->fixed_root = -1; + fld->child[i]->offset_parent = -1; + fld->child[i]->fixed_parent = -1; + // fld->child[i]->base_address = NULL; + fld->child[i]->field_size = 0; + fld->child[i]->field_fixed = -1; + fld->child[i]->parent = fld; + fld->child[i]->child = NULL; + fld->child[i]->current_element = 0; + constructTypeAndFields(fac, tmpTd, fld->child[i]); + } + } +} + + +/***************************************************************************** + *Function name + * lookup_named_type: search named type in the table + * internal function + *Input params + * fac : facility struct + * td : type descriptor + *Return value + * : either find the named type, or create a new LttType + ****************************************************************************/ + +LttType * lookup_named_type(LttFacility *fac, type_descriptor * td) +{ + LttType * lttType = NULL; + unsigned int i=0; + gchar * name; + + if(td->type_name){ + for(i=0;inamed_types_number; i++){ + if(fac->named_types[i] == NULL) break; + name = fac->named_types[i]->type_name; + if(g_ascii_strcasecmp(name, td->type_name)==0){ + lttType = fac->named_types[i]; + // if(lttType->element_name) g_free(lttType->element_name); + // lttType->element_name = NULL; + break; + } + } + } + + if(!lttType){ + lttType = g_new(LttType,1); + lttType->type_class = td->type; + if(td->fmt) lttType->fmt = g_strdup(td->fmt); + else lttType->fmt = NULL; + lttType->size = td->size; + lttType->enum_strings = NULL; + lttType->element_type = NULL; + lttType->element_number = 0; + lttType->element_name = NULL; + if(td->type_name){ + lttType->type_name = g_strdup(td->type_name); + fac->named_types[i] = lttType; /* i is initialized, checked. */ + } + else{ + lttType->type_name = NULL; + } + } + + return lttType; +} + + +/***************************************************************************** + *Function name + * ltt_facility_close : close a facility, decrease its usage count, + * if usage count = 0, release the memory + *Input params + * f : facility that will be closed + *Return value + * int : usage count ?? status + ****************************************************************************/ + +int ltt_facility_close(LttFacility *f) +{ + //release the memory it occupied + freeFacility(f); + + return 0; +} + +/***************************************************************************** + * Functions to release the memory occupied by the facility + ****************************************************************************/ + +void freeFacility(LttFacility * fac) +{ + unsigned int i; + g_free(fac->name); //free facility name + + //free event types + for(i=0;ievent_number;i++){ + freeEventtype(fac->events[i]); + } + g_free(fac->events); + + //free all named types + for(i=0;inamed_types_number;i++){ + freeLttNamedType(fac->named_types[i]); + fac->named_types[i] = NULL; + } + g_free(fac->named_types); + + //free the facility itself + g_free(fac); +} + +void freeEventtype(LttEventType * evType) +{ + LttType * root_type; + g_free(evType->name); + if(evType->description) + g_free(evType->description); + if(evType->root_field){ + root_type = evType->root_field->field_type; + freeLttField(evType->root_field); + freeLttType(&root_type); + } + + g_free(evType); +} + +void freeLttNamedType(LttType * type) +{ + g_free(type->type_name); + type->type_name = NULL; + freeLttType(&type); +} + +void freeLttType(LttType ** type) +{ + unsigned int i; + if(*type == NULL) return; + if((*type)->type_name){ + return; //this is a named type + } + if((*type)->element_name) + g_free((*type)->element_name); + if((*type)->fmt) + g_free((*type)->fmt); + if((*type)->enum_strings){ + for(i=0;i<(*type)->element_number;i++) + g_free((*type)->enum_strings[i]); + g_free((*type)->enum_strings); + } + + if((*type)->element_type){ + for(i=0;i<(*type)->element_number;i++) + freeLttType(&((*type)->element_type[i])); + g_free((*type)->element_type); + } + g_free(*type); + *type = NULL; +} + +void freeLttField(LttField * fld) +{ + int i; + int size = 0; + + if(fld->field_type){ + if(fld->field_type->type_class == LTT_ARRAY || + fld->field_type->type_class == LTT_SEQUENCE){ + size = 1; + }else if(fld->field_type->type_class == LTT_STRUCT){ + size = fld->field_type->element_number; + } + } + + if(fld->child){ + for(i=0; ichild[i])freeLttField(fld->child[i]); + } + g_free(fld->child); + } + g_free(fld); +} + +/***************************************************************************** + *Function name + * ltt_facility_name : obtain the facility's name + *Input params + * f : the facility that will be closed + *Return value + * char * : the facility's name + ****************************************************************************/ + +gchar *ltt_facility_name(LttFacility *f) +{ + return f->name; +} + +/***************************************************************************** + *Function name + * ltt_facility_checksum : obtain the facility's checksum + *Input params + * f : the facility that will be closed + *Return value + * LttChecksum : the checksum of the facility + ****************************************************************************/ + +LttChecksum ltt_facility_checksum(LttFacility *f) +{ + return f->checksum; +} + +/***************************************************************************** + *Function name + * ltt_facility_base_id : obtain the facility base id + *Input params + * f : the facility + *Return value + * : the base id of the facility + ****************************************************************************/ + +unsigned ltt_facility_base_id(LttFacility *f) +{ + return f->base_id; +} + +/***************************************************************************** + *Function name + * ltt_facility_eventtype_number: obtain the number of the event types + *Input params + * f : the facility that will be closed + *Return value + * unsigned : the number of the event types + ****************************************************************************/ + +unsigned ltt_facility_eventtype_number(LttFacility *f) +{ + return (f->event_number); +} + +/***************************************************************************** + *Function name + * ltt_facility_eventtype_get: obtain the event type according to event id + * from 0 to event_number - 1 + *Input params + * f : the facility that will be closed + *Return value + * LttEventType * : the event type required + ****************************************************************************/ + +LttEventType *ltt_facility_eventtype_get(LttFacility *f, unsigned i) +{ + return f->events[i]; +} + +/***************************************************************************** + *Function name + * ltt_facility_eventtype_get_by_name + * : obtain the event type according to event name + * event name is unique in the facility + *Input params + * f : the facility + * name : the name of the event + *Return value + * LttEventType * : the event type required + ****************************************************************************/ + +LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, gchar *name) +{ + unsigned int i; + LttEventType * ev = NULL; + + for(i=0;ievent_number;i++){ + LttEventType *iter_ev = f->events[i]; + if(g_ascii_strcasecmp(iter_ev->name, name) == 0) { + ev = iter_ev; + break; + } + } + return ev; +} + diff --git a/ltt/branches/poly/ltt-newlib/facility.h b/ltt/branches/poly/ltt-newlib/facility.h new file mode 100644 index 00000000..7398d659 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/facility.h @@ -0,0 +1,55 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Michel Dagenais + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef FACILITY_H +#define FACILITY_H + +#include + +/* Facilities are obtained from an opened trace. The structures associated + with a facility are released when the trace is closed. Each facility + is characterized by its name and checksum. */ + +GQuark ltt_facility_name(LttFacility *f); + +LttChecksum ltt_facility_checksum(LttFacility *f); + +/* open facility */ +void ltt_facility_open(LttTrace * t, GQuark facility_name); + +/* Discover the event types within the facility. The event type integer id + relative to the trace is from 0 to nb_event_types - 1. The event + type id within the trace is the relative id + the facility base event + id. */ + +unsigned ltt_facility_base_id(LttFacility *f); + +unsigned ltt_facility_eventtype_number(LttFacility *f); + +LttEventType *ltt_facility_eventtype_get(LttFacility *f, unsigned i); + +LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, GQuark name); + +int ltt_facility_close(LttFacility *f); + +/* Reserved facility names */ + +static const char *ltt_facility_name_core = "core"; + +#endif // FACILITY_H + diff --git a/ltt/branches/poly/ltt-newlib/ltt-private.h b/ltt/branches/poly/ltt-newlib/ltt-private.h new file mode 100644 index 00000000..a33b08b0 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/ltt-private.h @@ -0,0 +1,320 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2003-2004 Xiangxiu Yang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef LTT_PRIVATE_H +#define LTT_PRIVATE_H + +#include +#include +#include + +#define LTT_MAGIC_NUMBER 0x00D6B7ED +#define LTT_REV_MAGIC_NUMBER 0xEDB7D600 + +#define NSEC_PER_USEC 1000 + +#define LTT_PACKED_STRUCT __attribute__ ((packed)) + +#if 0 +/* enumeration definition */ + +typedef enum _BuildinEvent{ + TRACE_FACILITY_LOAD = 0, + TRACE_BLOCK_START = 17, + TRACE_BLOCK_END = 18, + TRACE_TIME_HEARTBEAT= 19 +} BuildinEvent; + + +/* structure definition */ + +typedef struct _FacilityLoad{ + gchar * name; + LttChecksum checksum; + guint32 base_code; +} LTT_PACKED_STRUCT FacilityLoad; + +typedef struct _BlockStart { + LttTime time; //Time stamp of this block + LttCycleCount cycle_count; //cycle count of the event + guint32 block_id; //block id +} LTT_PACKED_STRUCT BlockStart; + +typedef struct _BlockEnd { + LttTime time; //Time stamp of this block + LttCycleCount cycle_count; //cycle count of the event + guint32 block_id; //block id +} LTT_PACKED_STRUCT BlockEnd; +#endif //0 + + +typedef guint8 uint8_t; +typedef guint16 uint16_t; +typedef guint32 uint32_t; +typedef guint64 uint64_t; + +typedef struct _TimeHeartbeat { + LttTime time; //Time stamp of this block + uint64_t cycle_count; //cycle count of the event +} LTT_PACKED_STRUCT TimeHeartbeat; + +struct ltt_event_header_hb { + uint32_t timestamp; + unsigned char facility_id; + unsigned char event_id; + uint16_t event_size; +} __attribute((aligned(8))); + +struct ltt_event_header_nohb { + uint64_t timestamp; + unsigned char facility_id; + unsigned char event_id; + uint16_t event_size; +} __attribute((aligned(8))); + +struct ltt_trace_header { + uint32_t magic_number; + uint32_t arch_type; + uint32_t arch_variant; + uint8_t arch_size; + //uint32_t system_type; + uint8_t major_version; + uint8_t minor_version; + uint8_t flight_recorder; + uint8_t has_heartbeat; + uint8_t has_alignment; /* Event header alignment */ + uint8_t has_tsc; +} __attribute((aligned(8))); + + +struct ltt_block_start_header { + struct { + struct timeval timestamp; + uint64_t cycle_count; + } begin; + struct { + struct timeval timestamp; + uint64_t cycle_count; + } end; + uint32_t lost_size; /* Size unused at the end of the buffer */ + uint32_t buf_size; /* The size of this sub-buffer */ + struct ltt_trace_header trace; +} __attribute((aligned(8))); + + +struct _LttType{ + GQuark type_name; //type name if it is a named type + GQuark element_name; //elements name of the struct + gchar * fmt; + unsigned int size; + LttTypeEnum type_class; //which type + gchar ** enum_strings; //for enum labels + struct _LttType ** element_type; //for array, sequence and struct + unsigned element_number; //the number of elements + //for enum, array, sequence and structure +}; + +struct _LttEventType{ + gchar * name; + gchar * description; + int index; //id of the event type within the facility + LttFacility * facility; //the facility that contains the event type + LttField * root_field; //root field + //unsigned int latest_block; //the latest block using the event type + //unsigned int latest_event; //the latest event using the event type +}; + +struct _LttEvent{ + + /* Where is this event ? */ + LttTracefile *tracefile; + unsigned int block; + void *offset; + + union { /* choice by trace has_tsc */ + guint32 timestamp; /* truncated timestamp */ + guint32 delta; + } time; + + unsigned char facility_id; /* facility ID are never reused. */ + unsigned char event_id; + + LttTime event_time; + + void * data; //event data + + int count; //the number of overflow of cycle count + gint64 overflow_nsec; //precalculated nsec for overflows + TimeHeartbeat * last_heartbeat; //last heartbeat +}; + + +struct _LttField{ + unsigned field_pos; //field position within its parent + LttType * field_type; //field type, if it is root field + //then it must be struct type + + off_t offset_root; //offset from the root, -1:uninitialized + short fixed_root; //offset fixed according to the root + //-1:uninitialized, 0:unfixed, 1:fixed + off_t offset_parent; //offset from the parent,-1:uninitialized + short fixed_parent; //offset fixed according to its parent + //-1:uninitialized, 0:unfixed, 1:fixed + // void * base_address; //base address of the field ???? + + int field_size; //>0: size of the field, + //0 : uncertain + //-1: uninitialize + int sequ_number_size; //the size of unsigned used to save the + //number of elements in the sequence + + int element_size; //the element size of the sequence + int field_fixed; //0: field has string or sequence + //1: field has no string or sequenc + //-1: uninitialize + + struct _LttField * parent; + struct _LttField ** child; //for array, sequence and struct: + //list of fields, it may have only one + //field if the element is not a struct + unsigned current_element; //which element is currently processed +}; + + +struct _LttFacility{ + //gchar * name; //facility name + GQuark name; + unsigned int event_number; //number of events in the facility + guint32 checksum; //checksum of the facility + //guint32 base_id; //base id of the facility + LttEventType ** events; //array of event types + LttType ** named_types; + unsigned int named_types_number; +}; + +typedef struct _LttBuffer { + void * head; + unsigned int index; + + struct { + struct timeval timestamp; + uint64_t cycle_count; + } begin; + struct { + struct timeval timestamp; + uint64_t cycle_count; + } end; + uint32_t lost_size; /* Size unused at the end of the buffer */ + + /* Timekeeping */ + uint64_t tsc; /* Current timestamp counter */ + double nsecs_per_cycle; +} LttBuffer; + +struct _LttTracefile{ + gboolean cpu_online; //is the cpu online ? + GQuark name; //tracefile name + LttTrace * trace; //trace containing the tracefile + int fd; //file descriptor + off_t file_size; //file size + unsigned block_size; //block_size + unsigned int num_blocks; //number of blocks in the file + gboolean reverse_bo; //must we reverse byte order ? + + /* Current event */ + LttEvent event; //Event currently accessible in the trace + + /* Current block */ + LttBuffer buffer; //current buffer + guint32 buf_size; /* The size of blocks */ + + /* Time flow */ + //unsigned int count; //the number of overflow of cycle count + //double nsec_per_cycle; //Nsec per cycle + //TimeHeartbeat * last_heartbeat; //last heartbeat + + //LttCycleCount cycles_per_nsec_reciprocal; // Optimisation for speed + //void * last_event_pos; + + //LttTime prev_block_end_time; //the end time of previous block + //LttTime prev_event_time; //the time of the previous event + //LttCycleCount pre_cycle_count; //previous cycle count of the event +}; + +struct _LttTrace{ + GQuark pathname; //the pathname of the trace + guint facility_number; //the number of facilities + //LttSystemDescription * system_description;//system description + + //GPtrArray *control_tracefiles; //array of control tracefiles + //GPtrArray *per_cpu_tracefiles; //array of per cpu tracefiles + GPtrArray *facilities; //array of facilities + guint8 ltt_major_version; + guint8 ltt_minor_version; + guint8 flight_recorder; + guint8 has_heartbeat; + // guint8 alignment; + guint8 has_tsc; + + GData *tracefiles; //tracefiles groups +}; + +struct _LttEventPosition{ + LttTracefile *tracefile; + unsigned int block; + void *offset; + + /* Timekeeping */ + uint64_t tsc; /* Current timestamp counter */ +}; + +/* The characteristics of the system on which the trace was obtained + is described in a LttSystemDescription structure. */ + +struct _LttSystemDescription { + gchar *description; + gchar *node_name; + gchar *domain_name; + unsigned nb_cpu; + LttArchSize size; + LttArchEndian endian; + gchar *kernel_name; + gchar *kernel_release; + gchar *kernel_version; + gchar *machine; + gchar *processor; + gchar *hardware_platform; + gchar *operating_system; + //unsigned ltt_block_size; + LttTime trace_start; + LttTime trace_end; +}; + +/***************************************************************************** + macro for size of some data types + *****************************************************************************/ +// alignment -> dynamic! + +//#define TIMESTAMP_SIZE sizeof(guint32) +//#define EVENT_ID_SIZE sizeof(guint16) +//#define EVENT_HEADER_SIZE (TIMESTAMP_SIZE + EVENT_ID_SIZE) + +#define LTT_GET_BO(t) ((t)->reverse_bo) + + +#endif /* LTT_PRIVATE_H */ diff --git a/ltt/branches/poly/ltt-newlib/ltt-types.h b/ltt/branches/poly/ltt-newlib/ltt-types.h new file mode 100644 index 00000000..1076b8a6 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/ltt-types.h @@ -0,0 +1,91 @@ +/* This file is part of the Linux Trace Toolkit viewer + * Copyright (C) 2004-2005 Mathieu Desnoyers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#ifndef LTT_TYPES_H +#define LTT_TYPES_H + +/* Set of functions to access the types portably, given the trace as parameter. + * */ + +#include +//#include +#include +#include + + +/***************************************************************************** + *Function name + * ltt_get_int64 : get a 64 bits integer number + *Input params + * ptr : pointer to the integer + *Return value + * gint64 : a 64 bits integer + * + * Takes care of endianness + * + ****************************************************************************/ + +static inline gint64 ltt_get_int64(gboolean reverse_byte_order, void *ptr) +{ + guint64 value = *(guint64*)ptr; + return (gint64) (reverse_byte_order ? GUINT64_SWAP_LE_BE(value): value); +} + + +static inline guint64 ltt_get_uint64(gboolean reverse_byte_order, void *ptr) +{ + guint64 value = *(guint64*)ptr; + return (guint64) (reverse_byte_order ? GUINT64_SWAP_LE_BE(value): value); +} + +static inline gint32 ltt_get_int32(gboolean reverse_byte_order, void *ptr) +{ + guint32 value = *(guint32*)ptr; + return (gint32) (reverse_byte_order ? GUINT32_SWAP_LE_BE(value): value); +} + +static inline guint32 ltt_get_uint32(gboolean reverse_byte_order, void *ptr) +{ + guint32 value = *(guint32*)ptr; + return (guint32) (reverse_byte_order ? GUINT32_SWAP_LE_BE(value): value); +} + +static inline gint16 ltt_get_int16(gboolean reverse_byte_order, void *ptr) +{ + guint16 value = *(guint16*)ptr; + return (gint16) (reverse_byte_order ? GUINT16_SWAP_LE_BE(value): value); +} + +static inline guint16 ltt_get_uint16(gboolean reverse_byte_order, void *ptr) +{ + guint16 value = *(guint16*)ptr; + return (guint16) (reverse_byte_order ? GUINT16_SWAP_LE_BE(value): value); +} + +static inline LttTime ltt_get_time(gboolean reverse_byte_order, void *ptr) +{ + LttTime output; + + output.tv_sec = ltt_get_uint32(reverse_byte_order, ptr); + ptr += sizeof(guint32); + output.tv_nsec = ltt_get_uint32(reverse_byte_order, ptr); + + return output; +} + +#endif // LTT_TYPES_H diff --git a/ltt/branches/poly/ltt-newlib/ltt.h b/ltt/branches/poly/ltt-newlib/ltt.h new file mode 100644 index 00000000..0aa6daf9 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/ltt.h @@ -0,0 +1,135 @@ +/* This file is part of the Linux Trace Toolkit trace reading library + * Copyright (C) 2003-2004 Michel Dagenais + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License Version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef LTT_H +#define LTT_H + +#include +#include +#include + +/* A trace is associated with a tracing session run on a single, possibly + multi-cpu, system. It is defined as a pathname to a directory containing + all the relevant trace files. All the tracefiles for a trace were + generated in a single system for the same time period by the same + trace daemon. They simply contain different events. Typically control + tracefiles contain the important events (process creations and registering + tracing facilities) for all CPUs, and one file for each CPU contains all + the events for that CPU. All the tracefiles within the same trace directory + then use the exact same id numbers for event types. + + A tracefile (LttTracefile) contains a list of events (LttEvent) sorted + by time for each CPU; events from different CPUs may be slightly out of + order, especially using the (possibly drifting) cycle counters as + time unit. + + A facility is a list of event types (LttEventType), declared in a special + eventdefs file. A corresponding checksum differentiates different + facilities which would have the same name but a different content + (e.g., different versions). The files are stored within the trace + directory and are accessed automatically upon opening a trace. + The list of facilities (and associated checksum) used in a trace + must be known in order to properly decode the contained events. An event + is stored in the "facilities" control tracefile to denote each different + facility used. + + Event types (LttEventType) refer to data types (LttType) describing + their content. The data types supported are integer and unsigned integer + (of various length), enumerations (a special form of unsigned integer), + floating point (of various length), fixed size arrays, sequence + (variable sized arrays), structures and null terminated strings. + The elements of arrays and sequences, and the data members for + structures, may be of any nested data type (LttType). + + An LttField is a special object to denote a specific, possibly nested, + field within an event type. Suppose an event type socket_connect is a + structure containing two data members, source and destination, of type + socket_address. Type socket_address contains two unsigned integer + data members, ip and port. An LttField is different from a data type + structure member since it can denote a specific nested field, like the + source port, and store associated access information (byte offset within + the event data). The LttField objects are trace specific since the + contained information (byte offsets) may vary with the architecture + associated to the trace. */ + +typedef struct _LttTrace LttTrace; + +typedef struct _LttTracefile LttTracefile; + +typedef struct _LttFacility LttFacility; + +typedef struct _LttEventType LttEventType; + +typedef struct _LttType LttType; + +typedef struct _LttField LttField; + +typedef struct _LttEvent LttEvent; + +typedef struct _LttSystemDescription LttSystemDescription; + + +/* Checksums are used to differentiate facilities which have the same name + but differ. */ + +//typedef guint32 LttChecksum; + + +/* Events are usually stored with the easily obtained CPU clock cycle count, + ltt_cycle_count. This can be converted to the real time value, LttTime, + using linear interpolation between regularly sampled values (e.g. a few + times per second) of the real time clock with their corresponding + cycle count values. */ + + +typedef struct _TimeInterval{ + LttTime start_time; + LttTime end_time; +} TimeInterval; + + +typedef guint64 LttCycleCount; + + +/* Event positions are used to seek within a tracefile based on + the block number and event position within the block. */ + +typedef struct _LttEventPosition LttEventPosition; + + +/* Differences between architectures include word sizes, endianess, + alignment, floating point format and calling conventions. For a + packed binary trace, endianess and size matter, assuming that the + floating point format is standard (and is seldom used anyway). */ + +typedef enum _LttArchSize +{ LTT_LP32, LTT_ILP32, LTT_LP64, LTT_ILP64, LTT_UNKNOWN +} LttArchSize; + + +typedef enum _LttArchEndian +{ LTT_LITTLE_ENDIAN, LTT_BIG_ENDIAN +} LttArchEndian; + +typedef enum _LttTypeEnum +{ LTT_INT, LTT_UINT, LTT_FLOAT, LTT_STRING, LTT_ENUM, LTT_ARRAY, + LTT_SEQUENCE, LTT_STRUCT, LTT_UNION +} LttTypeEnum; + + +#endif // LTT_H diff --git a/ltt/branches/poly/ltt-newlib/parser.c b/ltt/branches/poly/ltt-newlib/parser.c new file mode 100644 index 00000000..8e409aa9 --- /dev/null +++ b/ltt/branches/poly/ltt-newlib/parser.c @@ -0,0 +1,1242 @@ +/* + +parser.c: Generate helper declarations and functions to trace events + from an event description file. + +Copyright (C) 2002, Xianxiu Yang +Copyright (C) 2002, Michel Dagenais +Copyright (C) 2005, Mathieu Desnoyers + +This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This program reads the ".xml" event definitions input files + and constructs structure for each event. + + The program uses a very simple tokenizer, called from a hand written + recursive descent parser to fill a data structure describing the events. + The result is a sequence of events definitions which refer to type + definitions. + + A table of named types is maintained to allow refering to types by name + when the same type is used at several places. Finally a sequence of + all types is maintained to facilitate the freeing of all type + information when the processing of an ".xml" file is finished. */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + + +#include "parser.h" + +/***************************************************************************** + *Function name + * getSize : translate from string to integer + *Input params + * in : input file handle + *Return values + * size + *****************************************************************************/ + +int getSize(parse_file *in) +{ + gchar *token; + + token = getToken(in); + if(in->type == NUMBER) { + if(g_ascii_strcasecmp(token,"1") == 0) return 0; + else if(g_ascii_strcasecmp(token,"2") == 0) return 1; + else if(g_ascii_strcasecmp(token,"4") == 0) return 2; + else if(g_ascii_strcasecmp(token,"8") == 0) return 3; + } + else if(in->type == NAME) { + if(g_ascii_strcasecmp(token,"short") == 0) return 4; + else if(g_ascii_strcasecmp(token,"medium") == 0) return 5; + else if(g_ascii_strcasecmp(token,"long") == 0) return 6; + } + in->error(in,"incorrect size specification"); + return -1; +} + +/***************************************************************************** + *Function name + * error_callback : print out error info + *Input params + * in : input file handle + * msg : message to be printed + ****************************************************************************/ + +void error_callback(parse_file *in, char *msg) +{ + if(in) + g_printf("Error in file %s, line %d: %s\n", in->name, in->lineno, msg); + else + printf("%s\n",msg); +} + +/************************************************************************** + * Function : + * getNameAttribute,getFormatAttribute,getSizeAttribute,getValueAttribute + * getValueStrAttribute + * Description : + * Read the attribute from the input file. + * + * Parameters : + * in , input file handle. + * + * Return values : + * address of the attribute. + * + **************************************************************************/ + +gchar * getNameAttribute(parse_file *in) +{ + gchar * token; + gunichar car; + GIOStatus status; + + token = getName(in); + if(g_ascii_strcasecmp("name",token))in->error(in,"name was expected"); + getEqual(in); + + status = seekNextChar(in, &car); + if(status == G_IO_STATUS_EOF || status == G_IO_STATUS_ERROR) + in->error(in,"name was expected"); + else if(car == '\"') token = getQuotedString(in); + else token = getName(in); + return token; +} + +char * getFormatAttribute(parse_file *in) +{ + char * token; + + //format is an option + token = getToken(in); + if(g_ascii_strcasecmp("/",token) == 0 || g_ascii_strcasecmp(">",token) == 0){ + ungetToken(in); + return NULL; + } + + if(g_ascii_strcasecmp("format",token))in->error(in,"format was expected"); + getEqual(in); + token = getQuotedString(in); + return token; +} + +int getSizeAttribute(parse_file *in) +{ + /* skip name and equal */ + getName(in); + getEqual(in); + + return getSize(in); +} + +int getValueAttribute(parse_file *in) +{ + /* skip name and equal */ + getName(in); + getEqual(in); + + return getNumber(in); +} + +//for