Esempio n. 1
0
int sdt_init(void)
{	int	ret;

	ret = misc_register(&sdt_dev);
	if (ret) {
		printk(KERN_WARNING "sdt: Unable to register misc device\n");
		return ret;
		}

	sdt_attach();

	dtrace_printf("sdt loaded: /dev/sdt now available\n");

	initted = 1;

	return 0;
}
Esempio n. 2
0
void sdt_init( void )
{
	if (0 == gSDTInited)
	{
		int majdevno = cdevsw_add(SDT_MAJOR, &sdt_cdevsw);
		
		if (majdevno < 0) {
			printf("sdt_init: failed to allocate a major number!\n");
			gSDTInited = 0;
			return;
		}

		if (dtrace_sdt_probes_restricted()) {
			return;
		}

		if (MH_MAGIC_KERNEL != _mh_execute_header.magic) {
			g_sdt_kernctl.mod_address = (vm_address_t)NULL;
			g_sdt_kernctl.mod_size = 0;
		} else {
			kernel_mach_header_t        *mh;
			struct load_command         *cmd;
			kernel_segment_command_t    *orig_ts = NULL, *orig_le = NULL;
			struct symtab_command       *orig_st = NULL;
			kernel_nlist_t		    *sym = NULL;
			char                        *strings;
			unsigned int 		    i;
			
			g_sdt_mach_module.sdt_nprobes = 0;
			g_sdt_mach_module.sdt_probes = NULL;
			
			g_sdt_kernctl.mod_address = (vm_address_t)&g_sdt_mach_module;
			g_sdt_kernctl.mod_size = 0;
			strncpy((char *)&(g_sdt_kernctl.mod_modname), "mach_kernel", KMOD_MAX_NAME);
			
			g_sdt_kernctl.mod_next = NULL;
			g_sdt_kernctl.mod_stale = NULL;
			g_sdt_kernctl.mod_id = 0;
			g_sdt_kernctl.mod_loadcnt = 1;
			g_sdt_kernctl.mod_loaded = 1;
			g_sdt_kernctl.mod_flags = 0;
			g_sdt_kernctl.mod_nenabled = 0;
			
			mh = &_mh_execute_header;
			cmd = (struct load_command*) &mh[1];
			for (i = 0; i < mh->ncmds; i++) {
				if (cmd->cmd == LC_SEGMENT_KERNEL) {
					kernel_segment_command_t *orig_sg = (kernel_segment_command_t *) cmd;
					
					if (LIT_STRNEQL(orig_sg->segname, SEG_TEXT))
						orig_ts = orig_sg;
					else if (LIT_STRNEQL(orig_sg->segname, SEG_LINKEDIT))
						orig_le = orig_sg;
					else if (LIT_STRNEQL(orig_sg->segname, ""))
						orig_ts = orig_sg; /* kexts have a single unnamed segment */
				}
				else if (cmd->cmd == LC_SYMTAB)
					orig_st = (struct symtab_command *) cmd;
				
				cmd = (struct load_command *) ((uintptr_t) cmd + cmd->cmdsize);
			}
			
			if ((orig_ts == NULL) || (orig_st == NULL) || (orig_le == NULL))
				return;
			
			sym = (kernel_nlist_t *)(orig_le->vmaddr + orig_st->symoff - orig_le->fileoff);
			strings = (char *)(orig_le->vmaddr + orig_st->stroff - orig_le->fileoff);
			
			for (i = 0; i < orig_st->nsyms; i++) {
				uint8_t n_type = sym[i].n_type & (N_TYPE | N_EXT);
				char *name = strings + sym[i].n_un.n_strx;
				const char *prev_name;
				unsigned long best;
				unsigned int j;
				
				/* Check that the symbol is a global and that it has a name. */
				if (((N_SECT | N_EXT) != n_type && (N_ABS | N_EXT) != n_type))
					continue;
				
				if (0 == sym[i].n_un.n_strx) /* iff a null, "", name. */
					continue;
				
				/* Lop off omnipresent leading underscore. */
				if (*name == '_')
					name += 1;
				
				if (strncmp(name, DTRACE_PROBE_PREFIX, sizeof(DTRACE_PROBE_PREFIX) - 1) == 0) {
					sdt_probedesc_t *sdpd = kmem_alloc(sizeof(sdt_probedesc_t), KM_SLEEP);
					int len = strlen(name) + 1;
					
					sdpd->sdpd_name = kmem_alloc(len, KM_SLEEP);
					strncpy(sdpd->sdpd_name, name, len); /* NUL termination is ensured. */
					
					prev_name = "<unknown>";
					best = 0;
					
					/*
					 * Find the symbol immediately preceding the sdt probe site just discovered,
					 * that symbol names the function containing the sdt probe.
					 */
					for (j = 0; j < orig_st->nsyms; j++) {
						uint8_t jn_type = sym[j].n_type & (N_TYPE | N_EXT);
						char *jname = strings + sym[j].n_un.n_strx;
						
						if (((N_SECT | N_EXT) != jn_type && (N_ABS | N_EXT) != jn_type))
							continue;
						
						if (0 == sym[j].n_un.n_strx) /* iff a null, "", name. */
							continue;
						
						if (*jname == '_')
							jname += 1;
						
						if (*(unsigned long *)sym[i].n_value <= (unsigned long)sym[j].n_value)
							continue;
						
						if ((unsigned long)sym[j].n_value > best) {
							best = (unsigned long)sym[j].n_value;
							prev_name = jname;
						}
					}
					
					sdpd->sdpd_func = kmem_alloc((len = strlen(prev_name) + 1), KM_SLEEP);
					strncpy(sdpd->sdpd_func, prev_name, len); /* NUL termination is ensured. */
					
					sdpd->sdpd_offset = *(unsigned long *)sym[i].n_value;
#if defined(__arm__)
					/* PR8353094 - mask off thumb-bit */
					sdpd->sdpd_offset &= ~0x1U;
#elif defined(__arm64__)
					sdpd->sdpd_offset &= ~0x1LU;
#endif  /* __arm__ */

#if 0
					printf("sdt_init: sdpd_offset=0x%lx, n_value=0x%lx, name=%s\n",
					    sdpd->sdpd_offset,  *(unsigned long *)sym[i].n_value, name);
#endif

					sdpd->sdpd_next = g_sdt_mach_module.sdt_probes;
					g_sdt_mach_module.sdt_probes = sdpd;
				} else {
					prev_name = name;
				}
			}
		}
		
		sdt_attach( (dev_info_t	*)(uintptr_t)majdevno, DDI_ATTACH );
		
		gSDTInited = 1;
	} else
		panic("sdt_init: called twice!\n");
}