/* 
 * enumerate all modules for process
 * pid: process id
 * lsc: load sample count
 */
static void enum_modules_for_process(pid_t pid, unsigned long lsc)
{
	bool find = false;
	char *pname;
	unsigned long name_offset;
	unsigned int options;
	struct task_struct *task;
	struct vm_area_struct *mmap;
	struct mm_struct *mm;

	task = px_find_task_by_pid(pid);

	if (task == NULL)
		return;

	mm = get_task_mm(task);
	if (mm != NULL)
	{
		down_read(&mm->mmap_sem);

		for (mmap = mm->mmap; mmap; mmap = mmap->vm_next)
		{
			if (is_valid_module(mmap))
			{
				memset(name, 0, (PATH_MAX) * sizeof(char));
				pname = px_d_path(mmap->vm_file, name, PATH_MAX);

				if (pname != NULL)
				{
					options = 0;

					if (find == false)
					{
						options |= MODULE_FLAG_1ST;
						find = true;
					}
					
					name_offset = get_filename_offset(pname);
					
					module_load_notif(pname, name_offset, pid,
						              mmap->vm_start, mmap->vm_end - mmap->vm_start,
						              options, lsc);
				}
			}
		}

		up_read(&mm->mmap_sem);
		mmput(mm);
	}

	if (find == false)
	{
		module_load_notif(task->comm, 0, pid,
				  LINUX_APP_BASE_LOW, 0,//mmap->vm_end - mmap->vm_start,
				  MODULE_FLAG_1ST, lsc);
	}

	return;
}
/*
 * enumerate all modules for process
 * pid: process id
 * lsc: load sample count
 */
static void enum_modules_for_process(pid_t pid, unsigned long long lsc, const char * proc_name)
{
	bool find = false;
	char *filename;
	unsigned long name_offset;
	unsigned int options;
	struct task_struct *task;
	struct vm_area_struct *mmap;
	struct mm_struct *mm;
	char * name = NULL;
	char * buffer = NULL;

	task = px_find_task_by_pid(pid);

	if (task == NULL)
		goto ret;

	name = kzalloc(PATH_MAX, GFP_ATOMIC);

	if (name == NULL)
		goto ret;

	buffer = kzalloc(PATH_MAX, GFP_ATOMIC);

	if (buffer == NULL)
		goto ret;

	mm = get_task_mm(task);
	if (mm != NULL)
	{
		down_read(&mm->mmap_sem);

		for (mmap = mm->mmap; mmap; mmap = mmap->vm_next)
		{
			if (is_valid_module(mmap))
			{
				memset(name, 0, (PATH_MAX) * sizeof(char));
				filename = px_d_path(mmap->vm_file, name, PATH_MAX);

				if (filename != NULL)
				{
					options = 0;

					if (find == false)
					{
						options |= MODULE_FLAG_1ST;
						find = true;

						if (proc_name != NULL)
						{
							/* for the first module (the executable image), if the process name is specified, use the specified one */
							strcpy(buffer, proc_name);
						}
						else
						{
							/*
							 * for the first module (the executable image), we need to get the process name again
							 * because it may be modified by changing the argv[0]
							 */
							if (get_proc_name(task, buffer) == 0)
							{
								/* failed to get the process name, use the orignal module name */
								strcpy(buffer, filename);
							}
						}

						/* save the orignal process name for checking if it will be updated later */
						notify_new_loaded_process(task, buffer);
					}
					else
					{
						memset(buffer, 0, sizeof(PATH_MAX));
						strcpy(buffer, filename);
					}

					name_offset = get_filename_offset(buffer);

					module_load_notif(buffer, name_offset, pid,
						              mmap->vm_start, mmap->vm_end - mmap->vm_start,
						              options, lsc);
				}
			}
		}

		up_read(&mm->mmap_sem);
		mmput(mm);
	}


	if (find == false)
	{
		module_load_notif(task->comm, 0, pid,
				  LINUX_APP_BASE_LOW, 0,//mmap->vm_end - mmap->vm_start,
				  MODULE_FLAG_1ST, lsc);
	}

ret:
	if (name != NULL)
		kfree(name);

	if (buffer != NULL)
		kfree(buffer);

	return;
}