Exemplo n.º 1
0
MSIZE MBArrowLook::GetDefaultSize(MArrow* pThumb)
{
	if(pThumb->m_nDirection==0){
		if(m_pArrowBitmaps[4]==NULL) return MArrowLook::GetDefaultSize(pThumb);
		return MSIZE(m_pArrowBitmaps[4]->GetWidth(), m_pArrowBitmaps[4]->GetHeight());
	}
	else{
		if(m_pArrowBitmaps[0]==NULL) return MArrowLook::GetDefaultSize(pThumb);
		return MSIZE(m_pArrowBitmaps[0]->GetWidth(), m_pArrowBitmaps[0]->GetHeight());
	}
}
Exemplo n.º 2
0
/*
 * doMemReallocUnsafe - reallocate a block, return NULL if it fails
 */
static void *doMemReAllocUnsafe( void *ptr, size_t size, WHO_PTR who )
{
    void        *tmp;

    size_t      orig_size;
#ifdef __WATCOMC__
    size_t      tsize;
#endif

    if( ptr != NULL ) {
#ifdef __WATCOMC__
        orig_size = MSIZE( ptr );
#else
        orig_size = 0xffffffff;
#endif
    } else {
        orig_size = 0;
    }

#ifdef TRMEM
    tmp = _trmem_realloc( ptr, size, who, trmemHandle );
#else
    who = who;
    tmp = realloc( ptr, size );
#endif
#ifdef __WATCOMC__
    if( tmp == NULL ) {
        tmp = doMemAllocUnsafe( size, who );
        if( tmp == NULL ) {
            return( NULL );
        }
        size = MSIZE( tmp );
        if( orig_size != 0 ) {
            tsize = orig_size;
            if( tsize > size ) {
                tsize = size;
            }
            memcpy( tmp, ptr, tsize );
            MemFree( ptr );
        }
    } else
#endif
    {
#ifdef __WATCOMC__
        size = MSIZE( tmp );
#endif
        if( size > orig_size ) {
            memset( &(((char *)tmp)[orig_size]), 0, size - orig_size );
        }
    }
    return( tmp );

} /* doMemReAllocUnsafe */
Exemplo n.º 3
0
/*
 * try_realloc_right - if heap is 
 *  |MALLOC|FREE and size is enough, then make as
 *  |REALLOC  |FRE  and return same pointer.
 *
 */
void* try_realloc_right(MALLOC target,void* origin, FREE right, size_t realsize)
{
	size_t rightnewF;

	if(MSIZE(target) + FSIZE(right) >= realsize)
	{
		rightnewF = realsize - MSIZE(target);
		divide_freeNode(right,rightnewF);
		delete_free(right);
		setAllocatedBlockSize(target,realsize);
		return M_TO_P(target);
	}
	return NULL;
}
Exemplo n.º 4
0
int socfpga_dwmmc_init(u32 regbase, int bus_width, int index)
{
    struct dwmci_host *host;
    unsigned long clk = cm_get_mmc_controller_clk_hz();

    if (clk == 0) {
        printf("%s: MMC clock is zero!", __func__);
        return -EINVAL;
    }

    /* calloc for zero init */
    host = calloc(1, sizeof(struct dwmci_host));
    if (!host) {
        printf("%s: calloc() failed!\n", __func__);
        return -ENOMEM;
    }

    host->name = "SOCFPGA DWMMC";
    host->ioaddr = (void *)regbase;
    host->buswidth = bus_width;
    host->clksel = socfpga_dwmci_clksel;
    host->dev_index = index;
    /* fixed clock divide by 4 which due to the SDMMC wrapper */
    host->bus_hz = clk;
    host->fifoth_val = MSIZE(0x2) |
                       RX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2 - 1) |
                       TX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2);

    return add_dwmci(host, host->bus_hz, 400000);
}
Exemplo n.º 5
0
static int dwmci_init(struct mmc *mmc)
{
	struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
	u32 fifo_size, fifoth_val;

	dwmci_writel(host, DWMCI_PWREN, 1);

	if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) {
		debug("%s[%d] Fail-reset!!\n",__func__,__LINE__);
		return -1;
	}

	dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
	dwmci_writel(host, DWMCI_INTMASK, 0);

	dwmci_writel(host, DWMCI_TMOUT, 0xFFFFFFFF);

	dwmci_writel(host, DWMCI_IDINTEN, 0);
	dwmci_writel(host, DWMCI_BMOD, 1);

	fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
	if (host->fifoth_val)
		fifoth_val = host->fifoth_val;
	else
		fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) |
			TX_WMARK(fifo_size/2);
	dwmci_writel(host, DWMCI_FIFOTH, fifoth_val);

	dwmci_writel(host, DWMCI_CLKENA, 0);
	dwmci_writel(host, DWMCI_CLKSRC, 0);

	return 0;
}
Exemplo n.º 6
0
static int dw_mci_init(u32 regbase, int bus_width, int index, int max_clock)
{
	struct dwmci_host *host = NULL;
	int  fifo_size = 0x20;

	host = malloc(sizeof(struct dwmci_host));
	if (!host) {
		printf("dwmci_host malloc fail!\n");
		return 1;
	}

	dw_mci_set_clk(index, max_clock * 2);

	host->name = NXP_NAME;
	host->ioaddr = (void *)regbase;
	host->buswidth = bus_width;
	host->clksel = dw_mci_clksel;
	host->dev_index = index;
	host->get_mmc_clk = dw_mci_get_clk;
	host->fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) | TX_WMARK(fifo_size/2);

	add_dwmci(host, max_clock, 400000);

	return 0;
}
Exemplo n.º 7
0
/*
 * mm_free - Freeing a block inserts new free chunks to explicit list/tree
 * and tries merging free chunks.
 */
void mm_free(void *ptr)
{
	MALLOC toFree = P_TO_M(ptr);
	insert_free(toFree,MSIZE(toFree));
	merge_freeChunks(toFree);
	//mm_check();
	return;
}
Exemplo n.º 8
0
/*
 * divide_malloc - 
 *  if size > newsize, make
 *   |MALLOC(size)| -> |MALLOC(newsize)|FREE|.
 *
 *
 */
void divide_malloc(MALLOC target, size_t newsize)
{
	size_t oldsize = MSIZE(target);
	if(newsize >= oldsize) return;
	void* newtarget = (char*)target + newsize;
	setAllocatedBlockSize(target,newsize);
	insert_free(newtarget, oldsize-newsize);
	return;
}
Exemplo n.º 9
0
ZBmNumLabel::ZBmNumLabel(const char* szName, MWidget* pParent, MListener* pListener)
: MWidget(szName, pParent, pListener)
{
	m_pLabelBitmap = NULL;
	m_AlignmentMode = MAM_RIGHT;
	m_nIndexOffset = 0;

	SetCharSize( MSIZE(32, 32));
}
Exemplo n.º 10
0
static int rockchip_dwmmc_probe(struct udevice *dev)
{
	struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
	struct dwmci_host *host = &priv->host;
	struct udevice *pwr_dev __maybe_unused;
	int ret;

#if CONFIG_IS_ENABLED(OF_PLATDATA)
	struct dtd_rockchip_rk3288_dw_mshc *dtplat = &plat->dtplat;

	host->name = dev->name;
	host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]);
	host->buswidth = dtplat->bus_width;
	host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk;
	host->priv = dev;
	host->dev_index = 0;
	priv->fifo_depth = dtplat->fifo_depth;
	priv->fifo_mode = 0;
	priv->minmax[0] = 400000;  /*  400 kHz */
	priv->minmax[1] = dtplat->max_frequency;

	ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
	if (ret < 0)
		return ret;
#else
	ret = clk_get_by_index(dev, 0, &priv->clk);
	if (ret < 0)
		return ret;
#endif
	host->fifoth_val = MSIZE(0x2) |
		RX_WMARK(priv->fifo_depth / 2 - 1) |
		TX_WMARK(priv->fifo_depth / 2);

	host->fifo_mode = priv->fifo_mode;

#ifdef CONFIG_PWRSEQ
	/* Enable power if needed */
	ret = uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq",
					   &pwr_dev);
	if (!ret) {
		ret = pwrseq_set_power(pwr_dev, true);
		if (ret)
			return ret;
	}
#endif
	dwmci_setup_cfg(&plat->cfg, host, priv->minmax[1], priv->minmax[0]);
	host->mmc = &plat->mmc;
	host->mmc->priv = &priv->host;
	host->mmc->dev = dev;
	upriv->mmc = host->mmc;

	return dwmci_probe(dev);
}
Exemplo n.º 11
0
BOOL AllocAndInitIpv6PktInfo(LPWSAMSG pWSAMsg)
{
    PBYTE CtrlBuf = (PBYTE)MALLOC(WSA_CMSG_SPACE(sizeof IN6_PKTINFO)); //caller frees heap allocated CtrlBuf

    if(NULL == CtrlBuf)
    {
        ERR("HeapAlloc");
        return FALSE;
    }

    pWSAMsg->Control.buf = (CHAR*)CtrlBuf;
    pWSAMsg->Control.len = (ULONG)MSIZE(CtrlBuf);

    return TRUE;
}
static int rockchip_dwmmc_probe(struct udevice *dev)
{
	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
	struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
	struct dwmci_host *host = &priv->host;
	struct udevice *pwr_dev __maybe_unused;
	u32 minmax[2];
	int ret;
	int fifo_depth;

	ret = clk_get_by_index(dev, 0, &priv->clk);
	if (ret < 0)
		return ret;
	priv->periph = ret;

	if (fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
				 "clock-freq-min-max", minmax, 2))
		return -EINVAL;

	fifo_depth = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
				    "fifo-depth", 0);
	if (fifo_depth < 0)
		return -EINVAL;

	host->fifoth_val = MSIZE(0x2) |
		RX_WMARK(fifo_depth / 2 - 1) | TX_WMARK(fifo_depth / 2);

	if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset, "fifo-mode"))
		host->fifo_mode = true;

#ifdef CONFIG_PWRSEQ
	/* Enable power if needed */
	ret = uclass_get_device_by_phandle(UCLASS_PWRSEQ, dev, "mmc-pwrseq",
					   &pwr_dev);
	if (!ret) {
		ret = pwrseq_set_power(pwr_dev, true);
		if (ret)
			return ret;
	}
#endif
	ret = add_dwmci(host, minmax[1], minmax[0]);
	if (ret)
		return ret;

	upriv->mmc = host->mmc;

	return 0;
}
Exemplo n.º 13
0
void MFrame::SetShade(bool bShade)
{
	if (!m_bCanShade) return;

	if (m_bShade == bShade) return;

	if(m_bShade==false){
		m_BeforeShade = MSIZE(m_Rect.w, m_Rect.h);
		SetSize(m_Rect.w, MTITLEBAR_HEIGHT);
		m_bShade = true;
		m_bResizable = false;
	}
	else{
		SetSize(m_BeforeShade);
		m_bShade = false;
		m_bResizable = true;
	}
}
Exemplo n.º 14
0
static int socfpga_dwmmc_ofdata_to_platdata(struct udevice *dev)
{
	/* FIXME: probe from DT eventually too/ */
	const unsigned long clk = cm_get_mmc_controller_clk_hz();

	struct dwmci_socfpga_priv_data *priv = dev_get_priv(dev);
	struct dwmci_host *host = &priv->host;
	int fifo_depth;

	if (clk == 0) {
		printf("DWMMC: MMC clock is zero!");
		return -EINVAL;
	}

	fifo_depth = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
				    "fifo-depth", 0);
	if (fifo_depth < 0) {
		printf("DWMMC: Can't get FIFO depth\n");
		return -EINVAL;
	}

	host->name = dev->name;
	host->ioaddr = (void *)dev_get_addr(dev);
	host->buswidth = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
					"bus-width", 4);
	host->clksel = socfpga_dwmci_clksel;

	/*
	 * TODO([email protected]): Remove the need for this hack.
	 * We only have one dwmmc block on gen5 SoCFPGA.
	 */
	host->dev_index = 0;
	/* Fixed clock divide by 4 which due to the SDMMC wrapper */
	host->bus_hz = clk;
	host->fifoth_val = MSIZE(0x2) |
		RX_WMARK(fifo_depth / 2 - 1) | TX_WMARK(fifo_depth / 2);
	priv->drvsel = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
				       "drvsel", 3);
	priv->smplsel = fdtdec_get_uint(gd->fdt_blob, dev->of_offset,
					"smplsel", 0);
	host->priv = priv;

	return 0;
}
Exemplo n.º 15
0
/*
 * getMem - get and clear memory
 */
static void *getMem( size_t size, WHO_PTR who )
{
    void        *tmp;

#ifdef TRMEM
    tmp = _trmem_alloc( size, who, trmemHandle );
#else
    who = who;
    tmp = malloc( size );
#endif
    if( tmp != NULL ) {
#ifdef __WATCOMC__
        size = MSIZE( tmp );
#endif
        memset( tmp, 0, size );
    }
    return( tmp );

} /* getMem */
Exemplo n.º 16
0
int socfpga_dwmmc_init(u32 regbase, int bus_width, int index)
{
	struct dwmci_host *host = NULL;
	host = calloc(sizeof(struct dwmci_host), 1);
	if (!host) {
		printf("dwmci_host calloc fail!\n");
		return -1;
	}

	host->name = SOCFPGA_NAME;
	host->ioaddr = (void *)regbase;
	host->buswidth = bus_width;
	host->clksel = socfpga_dwmci_clksel;
	host->dev_index = index;
	/* fixed clock divide by 4 which due to the SDMMC wrapper */
	host->bus_hz = CONFIG_SOCFPGA_DWMMC_BUS_HZ;
	host->fifoth_val = MSIZE(0x2) |
		RX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2 - 1) |
		TX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2);

	return add_dwmci(host, host->bus_hz, 400000);
}
Exemplo n.º 17
0
/*
 * mm_realloc - we check left chunk whether it is free chunk.
 *
 *  1. if it is free and its size is enough to cover reallocating size,
 *     change malloc/free info and return same pointer.
 *
 *  2. if not, check this chunk is rightmost( or left of rightmost
 *     free chunk)
 *
 *     2-1. if it is rightmost chunk (except free chunk), extend heap
 *          and return same pointer (change malloc/free info)
 *
 *     2-2. if not, extend heap with new size and return that poitner.
 */
void *mm_realloc(void *ptr, size_t size)
{
    MALLOC toRealloc = P_TO_M(ptr);
    void* retVal = NULL;
    size_t realSize = REQSIZE(size);
    size_t oldSize = MSIZE(toRealloc);
    if(realSize <= oldSize)
    {
	    divide_malloc(toRealloc, realSize);
	    return M_TO_P(toRealloc);
    }
    FREE right = (FREE)getRightBlock((void*)toRealloc);  
   if(!right)
   {
	   mem_sbrk(realSize - oldSize);
	   setAllocatedBlockSize(toRealloc,realSize);
	   return M_TO_P(toRealloc);

   } 
    if(right&&(*((size_t*)right)&1))
	    retVal = try_realloc_right(toRealloc,ptr,right,realSize);
    if(retVal) 
    {
	    return retVal;
    }
    FREE left = (FREE)getLeftBlock((void*)toRealloc);
    if(left&&(*((size_t*)left)&1))
	    retVal = try_realloc_leftRight(toRealloc,ptr,left,right,realSize);
    if(retVal) 
    {
	    return retVal;
    }
    retVal = mm_malloc(size);
    memcpy(retVal,ptr,oldSize - MHEAD);
    mm_free(ptr);
    return retVal;

}
Exemplo n.º 18
0
/// Create and Initialize mail queue.
/// \param[in]     queue_def     reference to the mail queue definition obtain with \ref osMailQ
/// \param[in]     thread_id     thread ID (obtained by \ref osThreadCreate or \ref osThreadGetId) or NULL.
/// \return mail queue ID for reference by other functions or NULL in case of error.
/// \note MUST REMAIN UNCHANGED: \b osMailCreate shall be consistent in every CMSIS-RTOS.
osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id)
{
	mbq_id mbq;

	(void) thread_id;

	port_sys_lock();

	unsigned size = MSIZE(queue_def->item_sz) + 1;

	mbq = core_sys_alloc(sizeof(mbq_t) + queue_def->queue_sz * size * sizeof(void*));

	if (mbq)
	{
		mbq->mem.limit = queue_def->queue_sz;
		mbq->mem.size  = size;
		mbq->mem.data  = mbq + 1;
		mem_init(&mbq->mem);
	}

	port_sys_unlock();

	return mbq;
}
Exemplo n.º 19
0
static int socfpga_dwmci_of_probe(const void *blob, int node, const int idx)
{
	/* FIXME: probe from DT eventually too/ */
	const unsigned long clk = cm_get_mmc_controller_clk_hz();

	struct dwmci_host *host;
	struct dwmci_socfpga_priv_data *priv;
	fdt_addr_t reg_base;
	int bus_width, fifo_depth;

	if (clk == 0) {
		printf("DWMMC%d: MMC clock is zero!", idx);
		return -EINVAL;
	}

	/* Get the register address from the device node */
	reg_base = fdtdec_get_addr(blob, node, "reg");
	if (!reg_base) {
		printf("DWMMC%d: Can't get base address\n", idx);
		return -EINVAL;
	}

	/* Get the bus width from the device node */
	bus_width = fdtdec_get_int(blob, node, "bus-width", 0);
	if (bus_width <= 0) {
		printf("DWMMC%d: Can't get bus-width\n", idx);
		return -EINVAL;
	}

	fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0);
	if (fifo_depth < 0) {
		printf("DWMMC%d: Can't get FIFO depth\n", idx);
		return -EINVAL;
	}

	/* Allocate the host */
	host = calloc(1, sizeof(*host));
	if (!host)
		return -ENOMEM;

	/* Allocate the priv */
	priv = calloc(1, sizeof(*priv));
	if (!priv) {
		free(host);
		return -ENOMEM;
	}

	host->name = "SOCFPGA DWMMC";
	host->ioaddr = (void *)reg_base;
	host->buswidth = bus_width;
	host->clksel = socfpga_dwmci_clksel;
	host->dev_index = idx;
	/* Fixed clock divide by 4 which due to the SDMMC wrapper */
	host->bus_hz = clk;
	host->fifoth_val = MSIZE(0x2) |
		RX_WMARK(fifo_depth / 2 - 1) | TX_WMARK(fifo_depth / 2);
	priv->drvsel = fdtdec_get_uint(blob, node, "drvsel", 3);
	priv->smplsel = fdtdec_get_uint(blob, node, "smplsel", 0);
	host->priv = priv;

	return add_dwmci(host, host->bus_hz, 400000);
}
Exemplo n.º 20
0
int __cdecl main()
{
    WSADATA             wsd;
    INT                 i = 0,
                        nErr = 0,
                        nStartup = 0,
                        rc = 0;
    SOCKET              sock = INVALID_SOCKET;
    SOCKADDR_STORAGE    addr = {0},
                        mcaddr = {0},
                        remoteaddr = {0};
    WSAOVERLAPPED       over = {0};
    WSABUF              wsabuf = {0};
    DWORD               dwBytes = 0,
                        dwFlags = 0,
                        dwRet = 0;
    IPV6_MREQ           mreq = {0};
    WSAMSG              wsamsg = {0};
    LPFN_WSARECVMSG     WSARecvMsg = NULL;


    __try
    {
        //Initialize Winsock

        nErr = WSAStartup(WS_VER,&wsd);
        if (nErr)
        {
            WSASetLastError(nErr);
            ERR("WSAStartup");
            __leave;
        }
        else
            nStartup++;


        // bind socket and register multicast

        mcaddr.ss_family = AF_INET6;

        InitMcastAddr((SOCKADDR*)&mcaddr,sizeof mcaddr);

        if (INVALID_SOCKET == (sock = socket(AF_INET6,SOCK_DGRAM,0)))
        {
            ERR("socket");
            __leave;
        }

        if(!RouteLookup((SOCKADDR*)&mcaddr,
                        sizeof mcaddr,
                        (SOCKADDR*)&addr,
                        sizeof addr
                       ))
        {
            ERR("RouteLookup");
            __leave;
        }

        SET_PORT((SOCKADDR*)&addr,DEFAULT_PORT);

        if (SOCKET_ERROR == bind(sock,(SOCKADDR*)&addr,sizeof addr))
        {
            ERR("bind");
            __leave;
        }

        mreq.ipv6mr_multiaddr = ((SOCKADDR_IN6*)&mcaddr)->sin6_addr;

        if (SOCKET_ERROR == setsockopt(sock,
                                       IPPROTO_IPV6,
                                       IPV6_ADD_MEMBERSHIP,
                                       (char*)&mreq,
                                       sizeof mreq
                                      ))
        {
            ERR("setsockopt IPV6_ADD_MEMBRESHIP");
            __leave;
        }

        // PktInfo

        if (!SetIpv6PktInfoOption(sock))
        {
            ERR("SetIpv6PktInfoOption");
            __leave;
        }

        if(!AllocAndInitIpv6PktInfo(&wsamsg))
        {
            ERR("AllocAndInitIpv6PktInfo");
            __leave;
        }

        // data buffer

        wsabuf.buf = (CHAR*)MALLOC(100);

        if(NULL == wsabuf.buf)
        {
            ERR("HeapAlloc");
            __leave;
        }

        wsabuf.len = (ULONG)MSIZE(wsabuf.buf);
        wsamsg.lpBuffers = &wsabuf;
        wsamsg.dwBufferCount = 1;

        // packet source address
        wsamsg.name = (SOCKADDR*)&remoteaddr;
        wsamsg.namelen = sizeof remoteaddr;

        //Post overlapped WSARecvMsg
        InitOverlap(&over);

        if (NULL == (WSARecvMsg = GetWSARecvMsgFunctionPointer()))
        {
            ERR("GetWSARecvMsgFunctionPointer");
            __leave;
        }

        if (SOCKET_ERROR == WSARecvMsg(sock,
                                       &wsamsg,
                                       &dwBytes,
                                       &over,
                                       NULL
                                      ))
        {
            if (WSA_IO_PENDING != WSAGetLastError())
            {
                ERR("WSARecvMsg");
                __leave;
            }
        }

        //set send interface

        if (SOCKET_ERROR == SetSendInterface(sock,(SOCKADDR*)&addr))
        {
            ERR("SetSendInterface");
            __leave;
        }

        //send msg to multicast


        SET_PORT((SOCKADDR*)&mcaddr,DEFAULT_PORT);

        //send a few packets
        for (i=0; i<5; i++)
        {

            if (SOCKET_ERROR == (rc = sendto(sock,
                                             TST_MSG,
                                             lstrlenA(TST_MSG),
                                             0,
                                             (SOCKADDR*)&mcaddr,
                                             sizeof (mcaddr)
                                            )))
            {
                ERR("sendto");
                __leave;
            }

            printf("Sent %d bytes\n",rc);
        }

        dwRet = WaitForSingleObject(over.hEvent,DEFAULT_WAIT);

        if (dwRet)
        {
            printf("%s\n",gai_strerror(dwRet));
            __leave;
        }

        if (!WSAGetOverlappedResult(sock,
                                    &over,
                                    &dwBytes,
                                    TRUE,
                                    &dwFlags
                                   ))
        {
            ERR("WSAGetOverlappedResult");
            __leave;
        }

        printf("WSARecvMsg completed with %d bytes\n",dwBytes);

        // if multicast packet do further processing
        if (MSG_MCAST & wsamsg.dwFlags)
        {
            if (ProcessIpv6Msg(&wsamsg))
            {
                //do something more interesting here
                printf("Recvd multicast msg.\n");
            }

        }

    }
    __finally
    {


        CLOSESOCK(sock);
        FREE(wsabuf.buf);
        FREE(wsamsg.Control.buf);
        CLOSESOCKEVENT(over.hEvent);
        if(nStartup) WSACleanup();
    }

    return 0;
}
Exemplo n.º 21
0
Rt_map *
setup(char **envp, auxv_t *auxv, Word _flags, char *_platform, int _syspagsz,
    char *_rtldname, ulong_t ld_base, ulong_t interp_base, int fd, Phdr *phdr,
    char *execname, char **argv, uid_t uid, uid_t euid, gid_t gid, gid_t egid,
    void *aoutdyn, int auxflags, uint_t *hwcap)
{
	Rt_map			*rlmp, *mlmp, *clmp, **tobj = NULL;
	Ehdr			*ehdr;
	rtld_stat_t		status;
	int			features = 0, ldsoexec = 0;
	size_t			eaddr, esize;
	char			*str, *argvname;
	Word			lmflags;
	mmapobj_result_t	*mpp;
	Fdesc			fdr = { 0 }, fdm = { 0 };
	Rej_desc		rej = { 0 };
	APlist			*ealp = NULL;

	/*
	 * Now that ld.so has relocated itself, initialize our own 'environ' so
	 * as to establish an address suitable for any libc requirements.
	 */
	_environ = (char **)((ulong_t)auxv - sizeof (char *));
	_init();
	_environ = envp;

	/*
	 * Establish a base time.  Total time diagnostics start from entering
	 * ld.so.1 here, however the base time is reset each time the ld.so.1
	 * is re-entered.  Note also, there will be a large time associated
	 * with the first diagnostic from ld.so.1, as bootstrapping ld.so.1
	 * and establishing the liblddbg infrastructure takes some time.
	 */
	(void) gettimeofday(&DBG_TOTALTIME, NULL);
	DBG_DELTATIME = DBG_TOTALTIME;

	/*
	 * Determine how ld.so.1 has been executed.
	 */
	if ((fd == -1) && (phdr == NULL)) {
		/*
		 * If we received neither the AT_EXECFD nor the AT_PHDR aux
		 * vector, ld.so.1 must have been invoked directly from the
		 * command line.
		 */
		ldsoexec = 1;

		/*
		 * AT_SUN_EXECNAME provides the most precise name, if it is
		 * available, otherwise fall back to argv[0].  At this time,
		 * there is no process name.
		 */
		if (execname)
			rtldname = execname;
		else if (argv[0])
			rtldname = argv[0];
		else
			rtldname = (char *)MSG_INTL(MSG_STR_UNKNOWN);
	} else {
		/*
		 * Otherwise, we have a standard process.  AT_SUN_EXECNAME
		 * provides the most precise name, if it is available,
		 * otherwise fall back to argv[0].  Provided the application
		 * is already mapped, the process is the application, so
		 * simplify the application name for use in any diagnostics.
		 */
		if (execname)
			argvname = execname;
		else if (argv[0])
			argvname = execname = argv[0];
		else
			argvname = execname = (char *)MSG_INTL(MSG_STR_UNKNOWN);

		if (fd == -1) {
			if ((str = strrchr(argvname, '/')) != NULL)
				procname = ++str;
			else
				procname = argvname;
		}

		/*
		 * At this point, we don't know the runtime linkers full path
		 * name.  The _rtldname passed to us is the SONAME of the
		 * runtime linker, which is typically /lib/ld.so.1 no matter
		 * what the full path is.   Use this for now, we'll reset the
		 * runtime linkers name once the application is analyzed.
		 */
		if (_rtldname) {
			if ((str = strrchr(_rtldname, '/')) != NULL)
				rtldname = ++str;
			else
				rtldname = _rtldname;
		} else
			rtldname = (char *)MSG_INTL(MSG_STR_UNKNOWN);

		/* exec() brought in two objects for us. Count the second one */
		cnt_map++;
	}

	/*
	 * Initialize any global variables.
	 */
	at_flags = _flags;

	if ((org_scapset->sc_plat = _platform) != NULL)
		org_scapset->sc_platsz = strlen(_platform);

	if (org_scapset->sc_plat == NULL)
		platform_name(org_scapset);
	if (org_scapset->sc_mach == NULL)
		machine_name(org_scapset);

	/*
	 * If pagesize is unspecified find its value.
	 */
	if ((syspagsz = _syspagsz) == 0)
		syspagsz = _sysconfig(_CONFIG_PAGESIZE);

	/*
	 * Add the unused portion of the last data page to the free space list.
	 * The page size must be set before doing this.  Here, _end refers to
	 * the end of the runtime linkers bss.  Note that we do not use the
	 * unused data pages from any included .so's to supplement this free
	 * space as badly behaved .os's may corrupt this data space, and in so
	 * doing ruin our data.
	 */
	eaddr = S_DROUND((size_t)&_end);
	esize = eaddr % syspagsz;
	if (esize) {
		esize = syspagsz - esize;
		addfree((void *)eaddr, esize);
	}

	/*
	 * Establish initial link-map list flags, and link-map list alists.
	 */
	if (alist_append(&lml_main.lm_lists, NULL, sizeof (Lm_cntl),
	    AL_CNT_LMLISTS) == NULL)
		return (0);
	lml_main.lm_flags |= LML_FLG_BASELM;
	lml_main.lm_lmid = LM_ID_BASE;
	lml_main.lm_lmidstr = (char *)MSG_ORIG(MSG_LMID_BASE);

	if (alist_append(&lml_rtld.lm_lists, NULL, sizeof (Lm_cntl),
	    AL_CNT_LMLISTS) == NULL)
		return (0);
	lml_rtld.lm_flags |= (LML_FLG_RTLDLM | LML_FLG_HOLDLOCK);
	lml_rtld.lm_tflags |= LML_TFLG_NOAUDIT;
	lml_rtld.lm_lmid = LM_ID_LDSO;
	lml_rtld.lm_lmidstr = (char *)MSG_ORIG(MSG_LMID_LDSO);

	/*
	 * Determine whether we have a secure executable.
	 */
	security(uid, euid, gid, egid, auxflags);

	/*
	 * Make an initial pass of environment variables to pick off those
	 * related to locale processing.  At the same time, collect and save
	 * any LD_XXXX variables for later processing.  Note that this later
	 * processing will be skipped if ld.so.1 is invoked from the command
	 * line with -e LD_NOENVIRON.
	 */
	if (envp && (readenv_user((const char **)envp, &ealp) == 1))
		return (0);

	/*
	 * If ld.so.1 has been invoked directly, process its arguments.
	 */
	if (ldsoexec) {
		/*
		 * Process any arguments that are specific to ld.so.1, and
		 * reorganize the process stack to effectively remove ld.so.1
		 * from the stack.  Reinitialize the environment pointer, as
		 * this pointer may have been shifted after skipping ld.so.1's
		 * arguments.
		 */
		if (rtld_getopt(argv, &envp, &auxv, &(lml_main.lm_flags),
		    &(lml_main.lm_tflags), (aoutdyn != 0)) == 1) {
			eprintf(&lml_main, ERR_NONE, MSG_INTL(MSG_USG_BADOPT));
			return (0);
		}
		_environ = envp;

		/*
		 * Open the object that ld.so.1 is to execute.
		 */
		argvname = execname = argv[0];

		if ((fd = open(argvname, O_RDONLY)) == -1) {
			int	err = errno;
			eprintf(&lml_main, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
			    argvname, strerror(err));
			return (0);
		}
	}

	/*
	 * Having processed any ld.so.1 command line options, return to process
	 * any LD_XXXX environment variables.
	 */
	if (ealp) {
		if (((rtld_flags & RT_FL_NOENVIRON) == 0) &&
		    (procenv_user(ealp, &(lml_main.lm_flags),
		    &(lml_main.lm_tflags), (aoutdyn != 0)) == 1))
			return (0);
		free(ealp);
	}

	/*
	 * Initialize a hardware capability descriptor for use in comparing
	 * each loaded object.  The aux vector must provide AF_SUN_HWCAPVERIFY,
	 * as prior to this setting any hardware capabilities that were found
	 * could not be relied upon.
	 */
	if (auxflags & AF_SUN_HWCAPVERIFY) {
		rtld_flags2 |= RT_FL2_HWCAP;
		org_scapset->sc_hw_1 = (Xword)hwcap[0];
		org_scapset->sc_hw_2 = (Xword)hwcap[1];
	}

	/*
	 * Create a mapping descriptor for ld.so.1.  We can determine our
	 * two segments information from known symbols.
	 */
	if ((mpp = calloc(2, sizeof (mmapobj_result_t))) == NULL)
		return (0);
	mpp[0].mr_addr = (caddr_t)M_PTRUNC(ld_base);
	mpp[0].mr_msize = (caddr_t)&_etext - mpp[0].mr_addr;
	mpp[0].mr_fsize = mpp[0].mr_msize;
	mpp[0].mr_prot = (PROT_READ | PROT_EXEC);

	mpp[1].mr_addr = (caddr_t)M_PTRUNC((uintptr_t)&r_debug);
	mpp[1].mr_msize = (caddr_t)&_end - mpp[1].mr_addr;
	mpp[1].mr_fsize = (caddr_t)&_edata - mpp[1].mr_addr;
	mpp[1].mr_prot = (PROT_READ | PROT_WRITE | PROT_EXEC);

	if ((fdr.fd_nname = stravl_insert(_rtldname, 0, 0, 0)) == NULL)
		return (0);
	if ((rlmp = elf_new_lmp(&lml_rtld, ALIST_OFF_DATA, &fdr,
	    (Addr)mpp->mr_addr, (size_t)((uintptr_t)eaddr - (uintptr_t)ld_base),
	    NULL, NULL, NULL)) == NULL)
		return (0);

	MMAPS(rlmp) = mpp;
	MMAPCNT(rlmp) = 2;
	PADSTART(rlmp) = (ulong_t)mpp[0].mr_addr;
	PADIMLEN(rlmp) = (ulong_t)mpp[0].mr_addr + (ulong_t)mpp[1].mr_addr +
	    (ulong_t)mpp[1].mr_msize;

	MODE(rlmp) |= (RTLD_LAZY | RTLD_NODELETE | RTLD_GLOBAL | RTLD_WORLD);
	FLAGS(rlmp) |= (FLG_RT_ANALYZED | FLG_RT_RELOCED | FLG_RT_INITDONE |
	    FLG_RT_INITCLCT | FLG_RT_FINICLCT | FLG_RT_MODESET);

	/*
	 * Initialize the runtime linkers information.
	 */
	interp = &_interp;
	interp->i_name = (char *)rtldname;
	interp->i_faddr = (caddr_t)ADDR(rlmp);
	ldso_plt_init(rlmp);

	/*
	 * Map in the file, if exec has not already done so, or if the file
	 * was passed as an argument to an explicit execution of ld.so.1 from
	 * the command line.
	 */
	if (fd != -1) {
		/*
		 * Map the file.  Once the object is mapped we no longer need
		 * the file descriptor.
		 */
		(void) rtld_fstat(fd, &status);
		fdm.fd_oname = argvname;
		fdm.fd_ftp = map_obj(&lml_main, &fdm, status.st_size, argvname,
		    fd, &rej);
		(void) close(fd);

		if (fdm.fd_ftp == NULL) {
			Conv_reject_desc_buf_t rej_buf;

			eprintf(&lml_main, ERR_FATAL,
			    MSG_INTL(err_reject[rej.rej_type]), argvname,
			    conv_reject_desc(&rej, &rej_buf, M_MACH));
			return (0);
		}

		/*
		 * Finish processing the loading of the file.
		 */
		if ((fdm.fd_nname = stravl_insert(argvname, 0, 0, 0)) == NULL)
			return (0);
		fdm.fd_dev = status.st_dev;
		fdm.fd_ino = status.st_ino;

		if ((mlmp = load_file(&lml_main, ALIST_OFF_DATA, NULL, &fdm,
		    NULL)) == NULL)
			return (0);

		/*
		 * We now have a process name for error diagnostics.
		 */
		if ((str = strrchr(argvname, '/')) != NULL)
			procname = ++str;
		else
			procname = argvname;

		if (ldsoexec) {
			mmapobj_result_t	*mpp = MMAPS(mlmp);
			uint_t			mnum, mapnum = MMAPCNT(mlmp);
			void			*brkbase = NULL;

			/*
			 * Since ld.so.1 was the primary executed object - the
			 * brk() base has not yet been initialized, we need to
			 * initialize it.  For an executable, initialize it to
			 * the end of the object.  For a shared object (ET_DYN)
			 * initialize it to the first page in memory.
			 */
			for (mnum = 0; mnum < mapnum; mnum++, mpp++)
				brkbase = mpp->mr_addr + mpp->mr_msize;

			if (brkbase == NULL)
				brkbase = (void *)syspagsz;

			if (_brk_unlocked(brkbase) == -1) {
				int	err = errno;

				eprintf(&lml_main, ERR_FATAL,
				    MSG_INTL(MSG_SYS_BRK), argvname,
				    strerror(err));
				return (0);
			}
		}
	} else {
		/*
		 * Set up function ptr and arguments according to the type
		 * of file class the executable is. (Currently only supported
		 * types are ELF and a.out format.)  Then create a link map
		 * for the executable.
		 */
		if (aoutdyn) {
#ifdef A_OUT
			mmapobj_result_t	*mpp;

			/*
			 * Create a mapping structure sufficient to describe
			 * a single two segments.  The ADDR() of the a.out is
			 * established as 0, which is required but the AOUT
			 * relocation code.
			 */
			if ((mpp =
			    calloc(sizeof (mmapobj_result_t), 2)) == NULL)
				return (0);

			if ((fdm.fd_nname =
			    stravl_insert(execname, 0, 0, 0)) == NULL)
				return (0);
			if ((mlmp = aout_new_lmp(&lml_main, ALIST_OFF_DATA,
			    &fdm, 0, 0, aoutdyn, NULL, NULL)) == NULL)
				return (0);

			/*
			 * Establish the true mapping information for the a.out.
			 */
			if (aout_get_mmap(&lml_main, mpp)) {
				free(mpp);
				return (0);
			}

			MSIZE(mlmp) =
			    (size_t)(mpp[1].mr_addr + mpp[1].mr_msize) -
			    S_ALIGN((size_t)mpp[0].mr_addr, syspagsz);
			MMAPS(mlmp) = mpp;
			MMAPCNT(mlmp) = 2;
			PADSTART(mlmp) = (ulong_t)mpp->mr_addr;
			PADIMLEN(mlmp) = mpp->mr_msize;

			/*
			 * Disable any object configuration cache (BCP apps
			 * bring in sbcp which can benefit from any object
			 * cache, but both the app and sbcp can't use the same
			 * objects).
			 */
			rtld_flags |= RT_FL_NOOBJALT;

			/*
			 * Make sure no-direct bindings are in effect.
			 */
			lml_main.lm_tflags |= LML_TFLG_NODIRECT;
#else
			eprintf(&lml_main, ERR_FATAL,
			    MSG_INTL(MSG_ERR_REJ_UNKFILE), argvname);
			return (0);
#endif
		} else if (phdr) {
			Phdr			*pptr;
			Off			i_offset = 0;
			Addr			base = 0;
			ulong_t			phsize;
			mmapobj_result_t	*mpp, *fmpp, *hmpp = NULL;
			uint_t			mapnum = 0;
			int			i;
			size_t			msize;

			/*
			 * Using the executables phdr address determine the base
			 * address of the input file.  NOTE, this assumes the
			 * program headers and elf header are part of the same
			 * mapped segment.  Although this has held for many
			 * years now, it might be more flexible if the kernel
			 * gave use the ELF headers start address, rather than
			 * the Program headers.
			 *
			 * Determine from the ELF header if we're been called
			 * from a shared object or dynamic executable.  If the
			 * latter, then any addresses within the object are used
			 * as is.  Addresses within shared objects must be added
			 * to the process's base address.
			 */
			ehdr = (Ehdr *)((Addr)phdr - phdr->p_offset);
			phsize = ehdr->e_phentsize;
			if (ehdr->e_type == ET_DYN)
				base = (Addr)ehdr;

			/*
			 * Allocate a mapping array to retain mapped segment
			 * information.
			 */
			if ((fmpp = mpp = calloc(ehdr->e_phnum,
			    sizeof (mmapobj_result_t))) == NULL)
				return (0);

			/*
			 * Extract the needed information from the segment
			 * headers.
			 */
			for (i = 0, pptr = phdr; i < ehdr->e_phnum; i++) {
				if (pptr->p_type == PT_INTERP) {
					i_offset = pptr->p_offset;
					interp->i_faddr =
					    (caddr_t)interp_base;
				}
				if ((pptr->p_type == PT_LOAD) &&
				    (pptr->p_filesz || pptr->p_memsz)) {
					int	perm = (PROT_READ | PROT_EXEC);
					size_t	off;

					if (i_offset && pptr->p_filesz &&
					    (i_offset >= pptr->p_offset) &&
					    (i_offset <=
					    (pptr->p_memsz + pptr->p_offset))) {
						interp->i_name = (char *)
						    pptr->p_vaddr + i_offset -
						    pptr->p_offset + base;
						i_offset = 0;
					}

					if (pptr->p_flags & PF_W)
						perm |= PROT_WRITE;

					/*
					 * Retain segments mapping info.  Round
					 * each segment to a page boundary, as
					 * this insures addresses are suitable
					 * for mprotect() if required.
					 */
					off = pptr->p_vaddr + base;
					if (hmpp == NULL) {
						hmpp = mpp;
						mpp->mr_addr = (caddr_t)ehdr;
					} else
						mpp->mr_addr = (caddr_t)off;

					off -= (size_t)(uintptr_t)mpp->mr_addr;
					mpp->mr_msize = pptr->p_memsz + off;
					mpp->mr_fsize = pptr->p_filesz + off;
					mpp->mr_prot = perm;

					mpp++, mapnum++;
				}

				pptr = (Phdr *)((ulong_t)pptr + phsize);
			}

			mpp--;
			msize = (size_t)(mpp->mr_addr + mpp->mr_msize) -
			    S_ALIGN((size_t)fmpp->mr_addr, syspagsz);

			if ((fdm.fd_nname =
			    stravl_insert(execname, 0, 0, 0)) == NULL)
				return (0);
			if ((mlmp = elf_new_lmp(&lml_main, ALIST_OFF_DATA,
			    &fdm, (Addr)hmpp->mr_addr, msize,
			    NULL, NULL, NULL)) == NULL)
				return (0);

			MMAPS(mlmp) = fmpp;
			MMAPCNT(mlmp) = mapnum;
			PADSTART(mlmp) = (ulong_t)fmpp->mr_addr;
			PADIMLEN(mlmp) = (ulong_t)fmpp->mr_addr +
			    (ulong_t)mpp->mr_addr + (ulong_t)mpp->mr_msize;
		}
	}

	/*
	 * Establish the interpretors name as that defined within the initial
	 * object (executable).  This provides for ORIGIN processing of ld.so.1
	 * dependencies.  Note, the NAME() of the object remains that which was
	 * passed to us as the SONAME on execution.
	 */
	if (ldsoexec == 0) {
		size_t	len = strlen(interp->i_name);

		if (expand(&interp->i_name, &len, 0, 0,
		    (PD_TKN_ISALIST | PD_TKN_CAP), rlmp) & PD_TKN_RESOLVED)
			fdr.fd_flags |= FLG_FD_RESOLVED;
	}
	fdr.fd_pname = interp->i_name;
	(void) fullpath(rlmp, &fdr);

	/*
	 * The runtime linker acts as a filtee for various dl*() functions that
	 * are defined in libc (and libdl).  Make sure this standard name for
	 * the runtime linker is also registered in the FullPathNode AVL tree.
	 */
	(void) fpavl_insert(&lml_rtld, rlmp, _rtldname, 0);

	/*
	 * Having established the true runtime linkers name, simplify the name
	 * for error diagnostics.
	 */
	if ((str = strrchr(PATHNAME(rlmp), '/')) != NULL)
		rtldname = ++str;
	else
		rtldname = PATHNAME(rlmp);

	/*
	 * Expand the fullpath name of the application.  This typically occurs
	 * as a part of loading an object, but as the kernel probably mapped
	 * it in, complete this processing now.
	 */
	(void) fullpath(mlmp, 0);

	/*
	 * Some troublesome programs will change the value of argv[0].  Dupping
	 * the process string protects us, and insures the string is left in
	 * any core files.
	 */
	if ((str = (char *)strdup(procname)) == NULL)
		return (0);
	procname = str;

	FLAGS(mlmp) |= (FLG_RT_ISMAIN | FLG_RT_MODESET);
	FLAGS1(mlmp) |= FL1_RT_USED;

	/*
	 * It's the responsibility of MAIN(crt0) to call it's _init and _fini
	 * section, therefore null out any INIT/FINI so that this object isn't
	 * collected during tsort processing.  And, if the application has no
	 * initarray or finiarray we can economize on establishing bindings.
	 */
	INIT(mlmp) = FINI(mlmp) = NULL;
	if ((INITARRAY(mlmp) == NULL) && (FINIARRAY(mlmp) == NULL))
		FLAGS1(mlmp) |= FL1_RT_NOINIFIN;

	/*
	 * Identify lddstub if necessary.
	 */
	if (lml_main.lm_flags & LML_FLG_TRC_LDDSTUB)
		FLAGS1(mlmp) |= FL1_RT_LDDSTUB;

	/*
	 * Retain our argument information for use in dlinfo.
	 */
	argsinfo.dla_argv = argv--;
	argsinfo.dla_argc = (long)*argv;
	argsinfo.dla_envp = envp;
	argsinfo.dla_auxv = auxv;

	(void) enter(0);

	/*
	 * Add our two main link-maps to the dynlm_list
	 */
	if (aplist_append(&dynlm_list, &lml_main, AL_CNT_DYNLIST) == NULL)
		return (0);

	if (aplist_append(&dynlm_list, &lml_rtld, AL_CNT_DYNLIST) == NULL)
		return (0);

	/*
	 * Reset the link-map counts for both lists.  The init count is used to
	 * track how many objects have pending init sections, this gets incre-
	 * mented each time an object is relocated.  Since ld.so.1 relocates
	 * itself, it's init count will remain zero.
	 * The object count is used to track how many objects have pending fini
	 * sections, as ld.so.1 handles its own fini we can zero its count.
	 */
	lml_main.lm_obj = 1;
	lml_rtld.lm_obj = 0;

	/*
	 * Initialize debugger information structure.  Some parts of this
	 * structure were initialized statically.
	 */
	r_debug.rtd_rdebug.r_map = (Link_map *)lml_main.lm_head;
	r_debug.rtd_rdebug.r_ldsomap = (Link_map *)lml_rtld.lm_head;
	r_debug.rtd_rdebug.r_ldbase = r_debug.rtd_rdebug.r_ldsomap->l_addr;
	r_debug.rtd_dynlmlst = &dynlm_list;

	/*
	 * Determine the dev/inode information for the executable to complete
	 * load_so() checking for those who might dlopen(a.out).
	 */
	if (rtld_stat(PATHNAME(mlmp), &status) == 0) {
		STDEV(mlmp) = status.st_dev;
		STINO(mlmp) = status.st_ino;
	}

	/*
	 * Initialize any configuration information.
	 */
	if (!(rtld_flags & RT_FL_NOCFG)) {
		if ((features = elf_config(mlmp, (aoutdyn != 0))) == -1)
			return (0);
	}

#if	defined(_ELF64)
	/*
	 * If this is a 64-bit process, determine whether this process has
	 * restricted the process address space to 32-bits.  Any dependencies
	 * that are restricted to a 32-bit address space can only be loaded if
	 * the executable has established this requirement.
	 */
	if (CAPSET(mlmp).sc_sf_1 & SF1_SUNW_ADDR32)
		rtld_flags2 |= RT_FL2_ADDR32;
#endif
	/*
	 * Establish any alternative capabilities, and validate this object
	 * if it defines it's own capabilities information.
	 */
	if (cap_alternative() == 0)
		return (0);

	if (cap_check_lmp(mlmp, &rej) == 0) {
		if (lml_main.lm_flags & LML_FLG_TRC_ENABLE) {
			/* LINTED */
			(void) printf(MSG_INTL(ldd_warn[rej.rej_type]),
			    NAME(mlmp), rej.rej_str);
		} else {
			/* LINTED */
			eprintf(&lml_main, ERR_FATAL,
			    MSG_INTL(err_reject[rej.rej_type]),
			    NAME(mlmp), rej.rej_str);
			return (0);
		}
	}

	/*
	 * Establish the modes of the initial object.  These modes are
	 * propagated to any preloaded objects and explicit shared library
	 * dependencies.
	 *
	 * If we're generating a configuration file using crle(1), remove
	 * any RTLD_NOW use, as we don't want to trigger any relocation proc-
	 * essing during crle(1)'s first past (this would just be unnecessary
	 * overhead).  Any filters are explicitly loaded, and thus RTLD_NOW is
	 * not required to trigger filter loading.
	 *
	 * Note, RTLD_NOW may have been established during analysis of the
	 * application had the application been built -z now.
	 */
	MODE(mlmp) |= (RTLD_NODELETE | RTLD_GLOBAL | RTLD_WORLD);

	if (rtld_flags & RT_FL_CONFGEN) {
		MODE(mlmp) |= RTLD_CONFGEN;
		MODE(mlmp) &= ~RTLD_NOW;
		rtld_flags2 &= ~RT_FL2_BINDNOW;
	}

	if ((MODE(mlmp) & RTLD_NOW) == 0) {
		if (rtld_flags2 & RT_FL2_BINDNOW)
			MODE(mlmp) |= RTLD_NOW;
		else
			MODE(mlmp) |= RTLD_LAZY;
	}

	/*
	 * If debugging was requested initialize things now that any cache has
	 * been established.  A user can specify LD_DEBUG=help to discover the
	 * list of debugging tokens available without running the application.
	 * However, don't allow this setting from a configuration file.
	 *
	 * Note, to prevent recursion issues caused by loading and binding the
	 * debugging libraries themselves, a local debugging descriptor is
	 * initialized.  Once the debugging setup has completed, this local
	 * descriptor is copied to the global descriptor which effectively
	 * enables diagnostic output.
	 *
	 * Ignore any debugging request if we're being monitored by a process
	 * that expects the old getpid() initialization handshake.
	 */
	if ((rpl_debug || prm_debug) && ((rtld_flags & RT_FL_DEBUGGER) == 0)) {
		Dbg_desc	_dbg_desc = {0};
		struct timeval	total = DBG_TOTALTIME;
		struct timeval	delta = DBG_DELTATIME;

		if (rpl_debug) {
			if (dbg_setup(rpl_debug, &_dbg_desc) == 0)
				return (0);
			if (_dbg_desc.d_extra & DBG_E_HELP_EXIT)
				rtldexit(&lml_main, 0);
		}
		if (prm_debug)
			(void) dbg_setup(prm_debug, &_dbg_desc);

		*dbg_desc = _dbg_desc;
		DBG_TOTALTIME = total;
		DBG_DELTATIME = delta;
	}

	/*
	 * Now that debugging is enabled generate any diagnostics from any
	 * previous events.
	 */
	if (DBG_ENABLED) {
		DBG_CALL(Dbg_cap_val(&lml_main, org_scapset, alt_scapset,
		    M_MACH));
		DBG_CALL(Dbg_file_config_dis(&lml_main, config->c_name,
		    features));

		DBG_CALL(Dbg_file_ldso(rlmp, envp, auxv,
		    LIST(rlmp)->lm_lmidstr, ALIST_OFF_DATA));

		if (THIS_IS_ELF(mlmp)) {
			DBG_CALL(Dbg_file_elf(&lml_main, PATHNAME(mlmp),
			    ADDR(mlmp), MSIZE(mlmp), LIST(mlmp)->lm_lmidstr,
			    ALIST_OFF_DATA));
		} else {
			DBG_CALL(Dbg_file_aout(&lml_main, PATHNAME(mlmp),
			    ADDR(mlmp), MSIZE(mlmp), LIST(mlmp)->lm_lmidstr,
			    ALIST_OFF_DATA));
		}
	}

	/*
	 * Enable auditing.
	 */
	if (rpl_audit || prm_audit || profile_lib) {
		int		ndx;
		const char	*aud[3];

		aud[0] = rpl_audit;
		aud[1] = prm_audit;
		aud[2] = profile_lib;

		/*
		 * Any global auditing (set using LD_AUDIT or LD_PROFILE) that
		 * can't be established is non-fatal.
		 */
		if ((auditors = calloc(1, sizeof (Audit_desc))) == NULL)
			return (0);

		for (ndx = 0; ndx < 3; ndx++) {
			if (aud[ndx]) {
				if ((auditors->ad_name =
				    strdup(aud[ndx])) == NULL)
					return (0);
				rtld_flags2 |= RT_FL2_FTL2WARN;
				(void) audit_setup(mlmp, auditors,
				    PD_FLG_EXTLOAD, NULL);
				rtld_flags2 &= ~RT_FL2_FTL2WARN;
			}
		}
		lml_main.lm_tflags |= auditors->ad_flags;
	}
	if (AUDITORS(mlmp)) {
		/*
		 * Any object required auditing (set with a DT_DEPAUDIT dynamic
		 * entry) that can't be established is fatal.
		 */
		if (FLAGS1(mlmp) & FL1_RT_GLOBAUD) {
			/*
			 * If this object requires global auditing, use the
			 * local auditing information to set the global
			 * auditing descriptor.  The effect is that a
			 * DT_DEPAUDIT act as an LD_AUDIT.
			 */
			if ((auditors == NULL) && ((auditors = calloc(1,
			    sizeof (Audit_desc))) == NULL))
				return (0);

			auditors->ad_name = AUDITORS(mlmp)->ad_name;
			if (audit_setup(mlmp, auditors, 0, NULL) == 0)
				return (0);
			lml_main.lm_tflags |= auditors->ad_flags;

			/*
			 * Clear the local auditor information.
			 */
			free((void *) AUDITORS(mlmp));
			AUDITORS(mlmp) = NULL;

		} else {
			/*
			 * Establish any local auditing.
			 */
			if (audit_setup(mlmp, AUDITORS(mlmp), 0, NULL) == 0)
				return (0);

			AFLAGS(mlmp) |= AUDITORS(mlmp)->ad_flags;
			lml_main.lm_flags |= LML_FLG_LOCAUDIT;
		}
	}

	/*
	 * Explicitly add the initial object and ld.so.1 to those objects being
	 * audited.  Note, although the ld.so.1 link-map isn't auditable,
	 * establish a cookie for ld.so.1 as this may be bound to via the
	 * dl*() family.
	 */
	if ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_MASK) {
		if (((audit_objopen(mlmp, mlmp) == 0) ||
		    (audit_objopen(mlmp, rlmp) == 0)) &&
		    (AFLAGS(mlmp) & LML_TFLG_AUD_MASK))
			return (0);
	}

	/*
	 * Map in any preloadable shared objects.  Establish the caller as the
	 * head of the main link-map list.  In the case of being exercised from
	 * lddstub, the caller gets reassigned to the first target shared object
	 * so as to provide intuitive diagnostics from ldd().
	 *
	 * Note, it is valid to preload a 4.x shared object with a 5.0
	 * executable (or visa-versa), as this functionality is required by
	 * ldd(1).
	 */
	clmp = mlmp;
	if (rpl_preload && (preload(rpl_preload, mlmp, &clmp) == 0))
		return (0);
	if (prm_preload && (preload(prm_preload, mlmp, &clmp) == 0))
		return (0);

	/*
	 * Load all dependent (needed) objects.
	 */
	if (analyze_lmc(&lml_main, ALIST_OFF_DATA, mlmp, mlmp, NULL) == NULL)
		return (0);

	/*
	 * Relocate all the dependencies we've just added.
	 *
	 * If this process has been established via crle(1), the environment
	 * variable LD_CONFGEN will have been set.  crle(1) may create this
	 * process twice.  The first time crle only needs to gather dependency
	 * information.  The second time, is to dldump() the images.
	 *
	 * If we're only gathering dependencies, relocation is unnecessary.
	 * As crle(1) may be building an arbitrary family of objects, they may
	 * not fully relocate either.  Hence the relocation phase is not carried
	 * out now, but will be called by crle(1) once all objects have been
	 * loaded.
	 */
	if ((rtld_flags & RT_FL_CONFGEN) == 0) {

		DBG_CALL(Dbg_util_nl(&lml_main, DBG_NL_STD));

		if (relocate_lmc(&lml_main, ALIST_OFF_DATA, mlmp,
		    mlmp, NULL) == 0)
			return (0);

		/*
		 * Inform the debuggers that basic process initialization is
		 * complete, and that the state of ld.so.1 (link-map lists,
		 * etc.) is stable.  This handshake enables the debugger to
		 * initialize themselves, and consequently allows the user to
		 * set break points in .init code.
		 *
		 * Most new debuggers use librtld_db to monitor activity events.
		 * Older debuggers indicated their presence by setting the
		 * DT_DEBUG entry in the dynamic executable (see elf_new_lm()).
		 * In this case, getpid() is called so that the debugger can
		 * catch the system call.  This old mechanism has some
		 * restrictions, as getpid() should not be called prior to
		 * basic process initialization being completed.  This
		 * restriction has become increasingly difficult to maintain,
		 * as the use of auditors, LD_DEBUG, and the initialization
		 * handshake with libc can result in "premature" getpid()
		 * calls.  The use of this getpid() handshake is expected to
		 * disappear at some point in the future, and there is intent
		 * to work towards that goal.
		 */
		rd_event(&lml_main, RD_DLACTIVITY, RT_CONSISTENT);
		rd_event(&lml_rtld, RD_DLACTIVITY, RT_CONSISTENT);

		if (rtld_flags & RT_FL_DEBUGGER) {
			r_debug.rtd_rdebug.r_flags |= RD_FL_ODBG;
			(void) getpid();
		}
	}

	/*
	 * Indicate preinit activity, and call any auditing routines.  These
	 * routines are called before initializing any threads via libc, or
	 * before collecting the complete set of .inits on the primary link-map.
	 * Although most libc interfaces are encapsulated in local routines
	 * within libc, they have been known to escape (ie. call a .plt).  As
	 * the appcert auditor uses preinit as a trigger to establish some
	 * external interfaces to the main link-maps libc, we need to activate
	 * this trigger before exercising any code within libc.  Additionally,
	 * I wouldn't put it past an auditor to add additional objects to the
	 * primary link-map.  Hence, we collect .inits after the audit call.
	 */
	rd_event(&lml_main, RD_PREINIT, 0);

	if (aud_activity ||
	    ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_ACTIVITY))
		audit_activity(mlmp, LA_ACT_CONSISTENT);
	if (aud_preinit ||
	    ((lml_main.lm_tflags | AFLAGS(mlmp)) & LML_TFLG_AUD_PREINIT))
		audit_preinit(mlmp);

	/*
	 * If we're creating initial configuration information, we're done
	 * now that the auditing step has been called.
	 */
	if (rtld_flags & RT_FL_CONFGEN) {
		leave(LIST(mlmp), 0);
		return (mlmp);
	}

	/*
	 * Sort the .init sections of all objects we've added.  If we're
	 * tracing we only need to execute this under ldd(1) with the -i or -u
	 * options.
	 */
	lmflags = lml_main.lm_flags;
	if (((lmflags & LML_FLG_TRC_ENABLE) == 0) ||
	    (lmflags & (LML_FLG_TRC_INIT | LML_FLG_TRC_UNREF))) {
		if ((tobj = tsort(mlmp, LIST(mlmp)->lm_init,
		    RT_SORT_REV)) == (Rt_map **)S_ERROR)
			return (0);
	}

	/*
	 * If we are tracing we're done.  This is the one legitimate use of a
	 * direct call to rtldexit() rather than return, as we don't want to
	 * return and jump to the application.
	 */
	if (lmflags & LML_FLG_TRC_ENABLE) {
		unused(&lml_main);
		rtldexit(&lml_main, 0);
	}

	/*
	 * Check if this instance of the linker should have a primary link
	 * map.  This flag allows multiple copies of the -same- -version-
	 * of the linker (and libc) to run in the same address space.
	 *
	 * Without this flag we only support one copy of the linker in a
	 * process because by default the linker will always try to
	 * initialize at one primary link map  The copy of libc which is
	 * initialized on a primary link map will initialize global TLS
	 * data which can be shared with other copies of libc in the
	 * process.  The problem is that if there is more than one copy
	 * of the linker, only one copy should link libc onto a primary
	 * link map, otherwise libc will attempt to re-initialize global
	 * TLS data.  So when a copy of the linker is loaded with this
	 * flag set, it will not initialize any primary link maps since
	 * presumably another copy of the linker will do this.
	 *
	 * Note that this flag only allows multiple copies of the -same-
	 * -version- of the linker (and libc) to coexist.  This approach
	 * will not work if we are trying to load different versions of
	 * the linker and libc into the same process.  The reason for
	 * this is that the format of the global TLS data may not be
	 * the same for different versions of libc.  In this case each
	 * different version of libc must have it's own primary link map
	 * and be able to maintain it's own TLS data.  The only way this
	 * can be done is by carefully managing TLS pointers on transitions
	 * between code associated with each of the different linkers.
	 * Note that this is actually what is done for processes in lx
	 * branded zones.  Although in the lx branded zone case, the
	 * other linker and libc are actually gld and glibc.  But the
	 * same general TLS management mechanism used by the lx brand
	 * would apply to any attempts to run multiple versions of the
	 * solaris linker and libc in a single process.
	 */
	if (auxflags & AF_SUN_NOPLM)
		rtld_flags2 |= RT_FL2_NOPLM;

	/*
	 * Establish any static TLS for this primary link-map.  Note, regardless
	 * of whether TLS is available, an initial handshake occurs with libc to
	 * indicate we're processing the primary link-map.  Having identified
	 * the primary link-map, initialize threads.
	 */
	if (rt_get_extern(&lml_main, mlmp) == 0)
		return (0);

	if ((rtld_flags2 & RT_FL2_NOPLM) == 0) {
		if (tls_statmod(&lml_main, mlmp) == 0)
			return (0);
		rt_thr_init(&lml_main);
		rtld_flags2 |= RT_FL2_PLMSETUP;
	} else {
		rt_thr_init(&lml_main);
	}

	/*
	 * Fire all dependencies .init sections.  Identify any unused
	 * dependencies, and leave the runtime linker - effectively calling
	 * the dynamic executables entry point.
	 */
	call_array(PREINITARRAY(mlmp), (uint_t)PREINITARRAYSZ(mlmp), mlmp,
	    SHT_PREINIT_ARRAY);

	if (tobj)
		call_init(tobj, DBG_INIT_SORT);

	rd_event(&lml_main, RD_POSTINIT, 0);

	unused(&lml_main);

	DBG_CALL(Dbg_util_call_main(mlmp));

	rtld_flags |= (RT_FL_OPERATION | RT_FL_APPLIC);

	leave(LIST(mlmp), 0);

	return (mlmp);
}